From 76ab1d2b6c9eedd861920ae6b6f8ee06aa482159 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 30 Apr 2018 14:20:56 -0400 Subject: [PATCH 01/47] support foo.* for ptr deref See #770 --- doc/langref.html.in | 6 ++++-- src/all_types.hpp | 6 ++++++ src/analyze.cpp | 1 + src/ast_render.cpp | 9 +++++++++ src/ir.cpp | 12 ++++++++++-- src/parser.cpp | 30 ++++++++++++++++++++++++------ test/behavior.zig | 1 + test/cases/pointers.zig | 14 ++++++++++++++ 8 files changed, 69 insertions(+), 10 deletions(-) create mode 100644 test/cases/pointers.zig diff --git a/doc/langref.html.in b/doc/langref.html.in index 16fafdaad9ab7b4652190caf8f63e093ca7aa639..9fb2ebf9f56e5a05b93b510e4b2fc674234793a4 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -5958,10 +5958,12 @@ MultiplyOperator = "||" | "*" | "/" | "%" | "**" | "*%" PrefixOpExpression = PrefixOp TypeExpr | SuffixOpExpression -SuffixOpExpression = ("async" option("<" SuffixOpExpression ">") SuffixOpExpression FnCallExpression) | PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression) +SuffixOpExpression = ("async" option("<" SuffixOpExpression ">") SuffixOpExpression FnCallExpression) | PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression | PtrDerefExpression) FieldAccessExpression = "." Symbol +PtrDerefExpression = ".*" + FnCallExpression = "(" list(Expression, ",") ")" ArrayAccessExpression = "[" Expression "]" @@ -5974,7 +5976,7 @@ ContainerInitBody = list(StructLiteralField, ",") | list(Expression, ",") StructLiteralField = "." Symbol "=" Expression -PrefixOp = "!" | "-" | "~" | "*" | ("&" option("align" "(" Expression option(":" Integer ":" Integer) ")" ) option("const") option("volatile")) | "?" | "??" | "-%" | "try" | "await" +PrefixOp = "!" | "-" | "~" | ("*" option("align" "(" Expression option(":" Integer ":" Integer) ")" ) option("const") option("volatile")) | "?" | "??" | "-%" | "try" | "await" PrimaryExpression = Integer | Float | String | CharLiteral | KeywordLiteral | GroupedExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | FnProto | AsmExpression | ContainerDecl | ("continue" option(":" Symbol)) | ErrorSetDecl | PromiseType diff --git a/src/all_types.hpp b/src/all_types.hpp index d1b2ad61d260ad360a01c0458e60eebf4a2abd9a..2993589f7bd665c4ea0c0774c3d4ee5e43fd874f 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -379,6 +379,7 @@ enum NodeType { NodeTypeArrayAccessExpr, NodeTypeSliceExpr, NodeTypeFieldAccessExpr, + NodeTypePtrDeref, NodeTypeUse, NodeTypeBoolLiteral, NodeTypeNullLiteral, @@ -603,6 +604,10 @@ struct AstNodeFieldAccessExpr { Buf *field_name; }; +struct AstNodePtrDerefExpr { + AstNode *target; +}; + enum PrefixOp { PrefixOpInvalid, PrefixOpBoolNot, @@ -911,6 +916,7 @@ struct AstNode { AstNodeCompTime comptime_expr; AstNodeAsmExpr asm_expr; AstNodeFieldAccessExpr field_access_expr; + AstNodePtrDerefExpr ptr_deref_expr; AstNodeContainerDecl container_decl; AstNodeStructField struct_field; AstNodeStringLiteral string_literal; diff --git a/src/analyze.cpp b/src/analyze.cpp index 1ecfe32f4c3ee1a49dc110e0c138b7f65b032837..99712cbfaf8aae161c8b651ad6d1585a2342404a 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -3275,6 +3275,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) { case NodeTypeUnreachable: case NodeTypeAsmExpr: case NodeTypeFieldAccessExpr: + case NodeTypePtrDeref: case NodeTypeStructField: case NodeTypeContainerInitExpr: case NodeTypeStructValueField: diff --git a/src/ast_render.cpp b/src/ast_render.cpp index 2c3e1fc8738ee9dddc81c9ec50b0a7e53f1ac83d..3e5ef0fcdb11f7de998af2cfb45f33897b4fe7f8 100644 --- a/src/ast_render.cpp +++ b/src/ast_render.cpp @@ -222,6 +222,8 @@ static const char *node_type_str(NodeType node_type) { return "AsmExpr"; case NodeTypeFieldAccessExpr: return "FieldAccessExpr"; + case NodeTypePtrDeref: + return "PtrDerefExpr"; case NodeTypeContainerDecl: return "ContainerDecl"; case NodeTypeStructField: @@ -696,6 +698,13 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { print_symbol(ar, rhs); break; } + case NodeTypePtrDeref: + { + AstNode *lhs = node->data.ptr_deref_expr.target; + render_node_ungrouped(ar, lhs); + fprintf(ar->f, ".*"); + break; + } case NodeTypeUndefinedLiteral: fprintf(ar->f, "undefined"); break; diff --git a/src/ir.cpp b/src/ir.cpp index 469900bf074253bf7602facf30f76503db3fe0a4..8c7232722e98affc6a1d8f827b2adf5957aafbc9 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -4548,8 +4548,14 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode } static IrInstruction *ir_gen_prefix_op_id_lval(IrBuilder *irb, Scope *scope, AstNode *node, IrUnOp op_id, LVal lval) { - assert(node->type == NodeTypePrefixOpExpr); - AstNode *expr_node = node->data.prefix_op_expr.primary_expr; + AstNode *expr_node; + if (node->type == NodeTypePrefixOpExpr) { + expr_node = node->data.prefix_op_expr.primary_expr; + } else if (node->type == NodeTypePtrDeref) { + expr_node = node->data.ptr_deref_expr.target; + } else { + zig_unreachable(); + } IrInstruction *value = ir_gen_node_extra(irb, expr_node, scope, lval); if (value == irb->codegen->invalid_instruction) @@ -6527,6 +6533,8 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop return ir_build_load_ptr(irb, scope, node, ptr_instruction); } + case NodeTypePtrDeref: + return ir_gen_prefix_op_id_lval(irb, scope, node, IrUnOpDereference, lval); case NodeTypeThisLiteral: return ir_lval_wrap(irb, scope, ir_gen_this_literal(irb, scope, node), lval); case NodeTypeBoolLiteral: diff --git a/src/parser.cpp b/src/parser.cpp index 4b70e904b82d23e877fa0c49cf2b352f5dd08621..c02546a99d8993661d5b2154b7d0f93e5ce70069 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -1046,11 +1046,12 @@ static AstNode *ast_parse_fn_proto_partial(ParseContext *pc, size_t *token_index } /* -SuffixOpExpression = ("async" option("<" SuffixOpExpression ">") SuffixOpExpression FnCallExpression) | PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression) +SuffixOpExpression = ("async" option("<" SuffixOpExpression ">") SuffixOpExpression FnCallExpression) | PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | PtrDerefExpression | SliceExpression) FnCallExpression : token(LParen) list(Expression, token(Comma)) token(RParen) ArrayAccessExpression : token(LBracket) Expression token(RBracket) SliceExpression = "[" Expression ".." option(Expression) "]" FieldAccessExpression : token(Dot) token(Symbol) +PtrDerefExpression = ".*" StructLiteralField : token(Dot) token(Symbol) token(Eq) Expression */ static AstNode *ast_parse_suffix_op_expr(ParseContext *pc, size_t *token_index, bool mandatory) { @@ -1131,13 +1132,27 @@ static AstNode *ast_parse_suffix_op_expr(ParseContext *pc, size_t *token_index, } else if (first_token->id == TokenIdDot) { *token_index += 1; - Token *name_token = ast_eat_token(pc, token_index, TokenIdSymbol); + Token *token = &pc->tokens->at(*token_index); - AstNode *node = ast_create_node(pc, NodeTypeFieldAccessExpr, first_token); - node->data.field_access_expr.struct_expr = primary_expr; - node->data.field_access_expr.field_name = token_buf(name_token); + if (token->id == TokenIdSymbol) { + *token_index += 1; + + AstNode *node = ast_create_node(pc, NodeTypeFieldAccessExpr, first_token); + node->data.field_access_expr.struct_expr = primary_expr; + node->data.field_access_expr.field_name = token_buf(token); + + primary_expr = node; + } else if (token->id == TokenIdStar) { + *token_index += 1; + + AstNode *node = ast_create_node(pc, NodeTypePtrDeref, first_token); + node->data.ptr_deref_expr.target = primary_expr; + + primary_expr = node; + } else { + ast_invalid_token_error(pc, token); + } - primary_expr = node; } else { return primary_expr; } @@ -3012,6 +3027,9 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont case NodeTypeFieldAccessExpr: visit_field(&node->data.field_access_expr.struct_expr, visit, context); break; + case NodeTypePtrDeref: + visit_field(&node->data.ptr_deref_expr.target, visit, context); + break; case NodeTypeUse: visit_field(&node->data.use.expr, visit, context); break; diff --git a/test/behavior.zig b/test/behavior.zig index 2c10c6d71bfd2cc85ad8cb331c257fd856411cd2..cb484b39a548bfe187f42b0ea0343cb81f42b67b 100644 --- a/test/behavior.zig +++ b/test/behavior.zig @@ -33,6 +33,7 @@ comptime { _ = @import("cases/misc.zig"); _ = @import("cases/namespace_depends_on_compile_var/index.zig"); _ = @import("cases/null.zig"); + _ = @import("cases/pointers.zig"); _ = @import("cases/pub_enum/index.zig"); _ = @import("cases/ref_var_in_if_after_if_2nd_switch_prong.zig"); _ = @import("cases/reflection.zig"); diff --git a/test/cases/pointers.zig b/test/cases/pointers.zig new file mode 100644 index 0000000000000000000000000000000000000000..87b3d25a74cfe1b7efa1841f4ed3e2d93e6c6c57 --- /dev/null +++ b/test/cases/pointers.zig @@ -0,0 +1,14 @@ +const std = @import("std"); +const assert = std.debug.assert; + +test "dereference pointer" { + comptime testDerefPtr(); + testDerefPtr(); +} + +fn testDerefPtr() void { + var x: i32 = 1234; + var y = &x; + y.* += 1; + assert(x == 1235); +} -- 2.54.0 From a35b366eb64272c6d4646aedc035a837ed0c3cb0 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 30 Apr 2018 20:35:54 -0400 Subject: [PATCH 02/47] [breaking] delete ptr deref prefix op start using zig-fmt-pointer-reform branch build of zig fmt to fix code to use the new syntax all of test/cases/* are processed, but there are more left to be done - all the std lib used by the behavior tests --- src/all_types.hpp | 1 - src/ast_render.cpp | 1 - src/ir.cpp | 2 - src/parser.cpp | 13 +- src/translate_c.cpp | 83 ++- std/debug/index.zig | 233 +++---- std/math/index.zig | 75 +-- std/mem.zig | 197 +++--- std/zig/parser.zig | 9 +- test/cases/align.zig | 86 ++- test/cases/alignof.zig | 6 +- test/cases/array.zig | 41 +- test/cases/bitcast.zig | 8 +- test/cases/bugs/394.zig | 17 +- test/cases/bugs/655.zig | 2 +- test/cases/bugs/656.zig | 11 +- test/cases/bugs/828.zig | 10 +- test/cases/bugs/920.zig | 19 +- test/cases/cast.zig | 72 ++- test/cases/coroutines.zig | 18 +- test/cases/defer.zig | 15 +- test/cases/enum.zig | 606 ++++++++++++++++-- test/cases/enum_with_members.zig | 10 +- test/cases/error.zig | 56 +- test/cases/eval.zig | 143 +++-- test/cases/fn.zig | 44 +- test/cases/for.zig | 44 +- test/cases/generics.zig | 42 +- test/cases/if.zig | 1 - test/cases/import/a_namespace.zig | 4 +- test/cases/ir_block_deps.zig | 4 +- test/cases/math.zig | 92 ++- test/cases/misc.zig | 225 ++++--- .../index.zig | 2 +- test/cases/null.zig | 27 +- ...ef_var_in_if_after_if_2nd_switch_prong.zig | 2 +- test/cases/reflection.zig | 5 +- test/cases/slice.zig | 8 +- test/cases/struct.zig | 83 ++- .../cases/struct_contains_null_ptr_itself.zig | 1 - .../cases/struct_contains_slice_of_itself.zig | 2 +- test/cases/switch.zig | 49 +- test/cases/switch_prong_err_enum.zig | 8 +- test/cases/switch_prong_implicit_cast.zig | 8 +- test/cases/try.zig | 8 +- test/cases/undefined.zig | 4 +- test/cases/union.zig | 87 +-- test/cases/var_args.zig | 25 +- test/cases/while.zig | 65 +- 49 files changed, 1694 insertions(+), 880 deletions(-) diff --git a/src/all_types.hpp b/src/all_types.hpp index 2993589f7bd665c4ea0c0774c3d4ee5e43fd874f..a25c99eddab061d9ed56e1f215a54590efe5296c 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -614,7 +614,6 @@ enum PrefixOp { PrefixOpBinNot, PrefixOpNegation, PrefixOpNegationWrap, - PrefixOpDereference, PrefixOpMaybe, PrefixOpUnwrapMaybe, }; diff --git a/src/ast_render.cpp b/src/ast_render.cpp index 3e5ef0fcdb11f7de998af2cfb45f33897b4fe7f8..0cb8bf4e93cc81d6e656921da5459e874df75df1 100644 --- a/src/ast_render.cpp +++ b/src/ast_render.cpp @@ -66,7 +66,6 @@ static const char *prefix_op_str(PrefixOp prefix_op) { case PrefixOpNegationWrap: return "-%"; case PrefixOpBoolNot: return "!"; case PrefixOpBinNot: return "~"; - case PrefixOpDereference: return "*"; case PrefixOpMaybe: return "?"; case PrefixOpUnwrapMaybe: return "??"; } diff --git a/src/ir.cpp b/src/ir.cpp index 8c7232722e98affc6a1d8f827b2adf5957aafbc9..ff5afe138c25ef4d9a3eb0473a4637509800249e 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -4696,8 +4696,6 @@ static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, Scope *scope, AstNod return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpNegation), lval); case PrefixOpNegationWrap: return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpNegationWrap), lval); - case PrefixOpDereference: - return ir_gen_prefix_op_id_lval(irb, scope, node, IrUnOpDereference, lval); case PrefixOpMaybe: return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpMaybe), lval); case PrefixOpUnwrapMaybe: diff --git a/src/parser.cpp b/src/parser.cpp index c02546a99d8993661d5b2154b7d0f93e5ce70069..4763d3b987a4c39be5ddf2634c8a2f60b81d3322 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -1165,10 +1165,8 @@ static PrefixOp tok_to_prefix_op(Token *token) { case TokenIdDash: return PrefixOpNegation; case TokenIdMinusPercent: return PrefixOpNegationWrap; case TokenIdTilde: return PrefixOpBinNot; - case TokenIdStar: return PrefixOpDereference; case TokenIdMaybe: return PrefixOpMaybe; case TokenIdDoubleQuestion: return PrefixOpUnwrapMaybe; - case TokenIdStarStar: return PrefixOpDereference; default: return PrefixOpInvalid; } } @@ -1214,7 +1212,7 @@ static AstNode *ast_parse_addr_of(ParseContext *pc, size_t *token_index) { /* PrefixOpExpression = PrefixOp ErrorSetExpr | SuffixOpExpression -PrefixOp = "!" | "-" | "~" | "*" | ("&" option("align" "(" Expression option(":" Integer ":" Integer) ")" ) option("const") option("volatile")) | "?" | "??" | "-%" | "try" | "await" +PrefixOp = "!" | "-" | "~" | ("*" option("align" "(" Expression option(":" Integer ":" Integer) ")" ) option("const") option("volatile")) | "?" | "??" | "-%" | "try" | "await" */ static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, size_t *token_index, bool mandatory) { Token *token = &pc->tokens->at(*token_index); @@ -1237,15 +1235,6 @@ static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, size_t *token_index, AstNode *node = ast_create_node(pc, NodeTypePrefixOpExpr, token); AstNode *parent_node = node; - if (token->id == TokenIdStarStar) { - // pretend that we got 2 star tokens - - parent_node = ast_create_node(pc, NodeTypePrefixOpExpr, token); - parent_node->data.prefix_op_expr.primary_expr = node; - parent_node->data.prefix_op_expr.prefix_op = PrefixOpDereference; - - node->column += 1; - } AstNode *prefix_op_expr = ast_parse_error_set_expr(pc, token_index, true); node->data.prefix_op_expr.primary_expr = prefix_op_expr; diff --git a/src/translate_c.cpp b/src/translate_c.cpp index 965a8963bda99753360abb5a48096cd1c50312cd..70a98dcc2eb8294acefa90676f907005dd645d3c 100644 --- a/src/translate_c.cpp +++ b/src/translate_c.cpp @@ -247,6 +247,12 @@ static AstNode *trans_create_node_field_access_str(Context *c, AstNode *containe return trans_create_node_field_access(c, container, buf_create_from_str(field_name)); } +static AstNode *trans_create_node_ptr_deref(Context *c, AstNode *child_node) { + AstNode *node = trans_create_node(c, NodeTypePtrDeref); + node->data.ptr_deref_expr.target = child_node; + return node; +} + static AstNode *trans_create_node_prefix_op(Context *c, PrefixOp op, AstNode *child_node) { AstNode *node = trans_create_node(c, NodeTypePrefixOpExpr); node->data.prefix_op_expr.prefix_op = op; @@ -1412,8 +1418,7 @@ static AstNode *trans_create_compound_assign_shift(Context *c, ResultUsed result AstNode *operation_type_cast = trans_c_cast(c, rhs_location, stmt->getComputationLHSType(), stmt->getLHS()->getType(), - trans_create_node_prefix_op(c, PrefixOpDereference, - trans_create_node_symbol(c, tmp_var_name))); + trans_create_node_ptr_deref(c, trans_create_node_symbol(c, tmp_var_name))); // result_type(... >> u5(rhs)) AstNode *result_type_cast = trans_c_cast(c, rhs_location, @@ -1426,7 +1431,7 @@ static AstNode *trans_create_compound_assign_shift(Context *c, ResultUsed result // *_ref = ... AstNode *assign_statement = trans_create_node_bin_op(c, - trans_create_node_prefix_op(c, PrefixOpDereference, + trans_create_node_ptr_deref(c, trans_create_node_symbol(c, tmp_var_name)), BinOpTypeAssign, result_type_cast); @@ -1436,7 +1441,7 @@ static AstNode *trans_create_compound_assign_shift(Context *c, ResultUsed result // break :x *_ref child_scope->node->data.block.statements.append( trans_create_node_break(c, label_name, - trans_create_node_prefix_op(c, PrefixOpDereference, + trans_create_node_ptr_deref(c, trans_create_node_symbol(c, tmp_var_name)))); } @@ -1483,11 +1488,11 @@ static AstNode *trans_create_compound_assign(Context *c, ResultUsed result_used, if (rhs == nullptr) return nullptr; AstNode *assign_statement = trans_create_node_bin_op(c, - trans_create_node_prefix_op(c, PrefixOpDereference, + trans_create_node_ptr_deref(c, trans_create_node_symbol(c, tmp_var_name)), BinOpTypeAssign, trans_create_node_bin_op(c, - trans_create_node_prefix_op(c, PrefixOpDereference, + trans_create_node_ptr_deref(c, trans_create_node_symbol(c, tmp_var_name)), bin_op, rhs)); @@ -1496,7 +1501,7 @@ static AstNode *trans_create_compound_assign(Context *c, ResultUsed result_used, // break :x *_ref child_scope->node->data.block.statements.append( trans_create_node_break(c, label_name, - trans_create_node_prefix_op(c, PrefixOpDereference, + trans_create_node_ptr_deref(c, trans_create_node_symbol(c, tmp_var_name)))); return child_scope->node; @@ -1817,13 +1822,13 @@ static AstNode *trans_create_post_crement(Context *c, ResultUsed result_used, Tr // const _tmp = *_ref; Buf* tmp_var_name = buf_create_from_str("_tmp"); AstNode *tmp_var_decl = trans_create_node_var_decl_local(c, true, tmp_var_name, nullptr, - trans_create_node_prefix_op(c, PrefixOpDereference, + trans_create_node_ptr_deref(c, trans_create_node_symbol(c, ref_var_name))); child_scope->node->data.block.statements.append(tmp_var_decl); // *_ref += 1; AstNode *assign_statement = trans_create_node_bin_op(c, - trans_create_node_prefix_op(c, PrefixOpDereference, + trans_create_node_ptr_deref(c, trans_create_node_symbol(c, ref_var_name)), assign_op, trans_create_node_unsigned(c, 1)); @@ -1871,14 +1876,14 @@ static AstNode *trans_create_pre_crement(Context *c, ResultUsed result_used, Tra // *_ref += 1; AstNode *assign_statement = trans_create_node_bin_op(c, - trans_create_node_prefix_op(c, PrefixOpDereference, + trans_create_node_ptr_deref(c, trans_create_node_symbol(c, ref_var_name)), assign_op, trans_create_node_unsigned(c, 1)); child_scope->node->data.block.statements.append(assign_statement); // break :x *_ref - AstNode *deref_expr = trans_create_node_prefix_op(c, PrefixOpDereference, + AstNode *deref_expr = trans_create_node_ptr_deref(c, trans_create_node_symbol(c, ref_var_name)); child_scope->node->data.block.statements.append(trans_create_node_break(c, label_name, deref_expr)); @@ -1923,7 +1928,7 @@ static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransSc if (is_fn_ptr) return value_node; AstNode *unwrapped = trans_create_node_prefix_op(c, PrefixOpUnwrapMaybe, value_node); - return trans_create_node_prefix_op(c, PrefixOpDereference, unwrapped); + return trans_create_node_ptr_deref(c, unwrapped); } case UO_Plus: emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_Plus"); @@ -4469,27 +4474,45 @@ static AstNode *parse_ctok_suffix_op_expr(Context *c, CTokenize *ctok, size_t *t } } -static PrefixOp ctok_to_prefix_op(CTok *token) { - switch (token->id) { - case CTokIdBang: return PrefixOpBoolNot; - case CTokIdMinus: return PrefixOpNegation; - case CTokIdTilde: return PrefixOpBinNot; - case CTokIdAsterisk: return PrefixOpDereference; - default: return PrefixOpInvalid; - } -} static AstNode *parse_ctok_prefix_op_expr(Context *c, CTokenize *ctok, size_t *tok_i) { CTok *op_tok = &ctok->tokens.at(*tok_i); - PrefixOp prefix_op = ctok_to_prefix_op(op_tok); - if (prefix_op == PrefixOpInvalid) { - return parse_ctok_suffix_op_expr(c, ctok, tok_i); - } - *tok_i += 1; - AstNode *prefix_op_expr = parse_ctok_prefix_op_expr(c, ctok, tok_i); - if (prefix_op_expr == nullptr) - return nullptr; - return trans_create_node_prefix_op(c, prefix_op, prefix_op_expr); + switch (op_tok->id) { + case CTokIdBang: + { + *tok_i += 1; + AstNode *prefix_op_expr = parse_ctok_prefix_op_expr(c, ctok, tok_i); + if (prefix_op_expr == nullptr) + return nullptr; + return trans_create_node_prefix_op(c, PrefixOpBoolNot, prefix_op_expr); + } + case CTokIdMinus: + { + *tok_i += 1; + AstNode *prefix_op_expr = parse_ctok_prefix_op_expr(c, ctok, tok_i); + if (prefix_op_expr == nullptr) + return nullptr; + return trans_create_node_prefix_op(c, PrefixOpNegation, prefix_op_expr); + } + case CTokIdTilde: + { + *tok_i += 1; + AstNode *prefix_op_expr = parse_ctok_prefix_op_expr(c, ctok, tok_i); + if (prefix_op_expr == nullptr) + return nullptr; + return trans_create_node_prefix_op(c, PrefixOpBinNot, prefix_op_expr); + } + case CTokIdAsterisk: + { + *tok_i += 1; + AstNode *prefix_op_expr = parse_ctok_prefix_op_expr(c, ctok, tok_i); + if (prefix_op_expr == nullptr) + return nullptr; + return trans_create_node_ptr_deref(c, prefix_op_expr); + } + default: + return parse_ctok_suffix_op_expr(c, ctok, tok_i); + } } static void process_macro(Context *c, CTokenize *ctok, Buf *name, const char *char_ptr) { diff --git a/std/debug/index.zig b/std/debug/index.zig index 9057f157ded5744dd5714adb742b7963fb9ccc59..36ac2e8a3fa007bab0142d02ac74d11bbb75b9bf 100644 --- a/std/debug/index.zig +++ b/std/debug/index.zig @@ -104,9 +104,7 @@ pub fn panic(comptime format: []const u8, args: ...) noreturn { var panicking: u8 = 0; // TODO make this a bool -pub fn panicExtra(trace: ?&const builtin.StackTrace, first_trace_addr: ?usize, - comptime format: []const u8, args: ...) noreturn -{ +pub fn panicExtra(trace: ?&const builtin.StackTrace, first_trace_addr: ?usize, comptime format: []const u8, args: ...) noreturn { @setCold(true); if (@atomicRmw(u8, &panicking, builtin.AtomicRmwOp.Xchg, 1, builtin.AtomicOrder.SeqCst) == 1) { @@ -132,9 +130,7 @@ const WHITE = "\x1b[37;1m"; const DIM = "\x1b[2m"; const RESET = "\x1b[0m"; -pub fn writeStackTrace(stack_trace: &const builtin.StackTrace, out_stream: var, allocator: &mem.Allocator, - debug_info: &ElfStackTrace, tty_color: bool) !void -{ +pub fn writeStackTrace(stack_trace: &const builtin.StackTrace, out_stream: var, allocator: &mem.Allocator, debug_info: &ElfStackTrace, tty_color: bool) !void { var frame_index: usize = undefined; var frames_left: usize = undefined; if (stack_trace.index < stack_trace.instruction_addresses.len) { @@ -154,9 +150,7 @@ pub fn writeStackTrace(stack_trace: &const builtin.StackTrace, out_stream: var, } } -pub fn writeCurrentStackTrace(out_stream: var, allocator: &mem.Allocator, - debug_info: &ElfStackTrace, tty_color: bool, start_addr: ?usize) !void -{ +pub fn writeCurrentStackTrace(out_stream: var, allocator: &mem.Allocator, debug_info: &ElfStackTrace, tty_color: bool, start_addr: ?usize) !void { const AddressState = union(enum) { NotLookingForStartAddress, LookingForStartAddress: usize, @@ -166,14 +160,14 @@ pub fn writeCurrentStackTrace(out_stream: var, allocator: &mem.Allocator, // else AddressState.NotLookingForStartAddress; var addr_state: AddressState = undefined; if (start_addr) |addr| { - addr_state = AddressState { .LookingForStartAddress = addr }; + addr_state = AddressState{ .LookingForStartAddress = addr }; } else { addr_state = AddressState.NotLookingForStartAddress; } var fp = @ptrToInt(@frameAddress()); - while (fp != 0) : (fp = *@intToPtr(&const usize, fp)) { - const return_address = *@intToPtr(&const usize, fp + @sizeOf(usize)); + while (fp != 0) : (fp = @intToPtr(&const usize, fp).*) { + const return_address = @intToPtr(&const usize, fp + @sizeOf(usize)).*; switch (addr_state) { AddressState.NotLookingForStartAddress => {}, @@ -200,32 +194,32 @@ fn printSourceAtAddress(debug_info: &ElfStackTrace, out_stream: var, address: us // in practice because the compiler dumps everything in a single // object file. Future improvement: use external dSYM data when // available. - const unknown = macho.Symbol { .name = "???", .address = address }; + const unknown = macho.Symbol{ + .name = "???", + .address = address, + }; const symbol = debug_info.symbol_table.search(address) ?? &unknown; - try out_stream.print(WHITE ++ "{}" ++ RESET ++ ": " ++ - DIM ++ ptr_hex ++ " in ??? (???)" ++ RESET ++ "\n", - symbol.name, address); + try out_stream.print(WHITE ++ "{}" ++ RESET ++ ": " ++ DIM ++ ptr_hex ++ " in ??? (???)" ++ RESET ++ "\n", symbol.name, address); }, else => { const compile_unit = findCompileUnit(debug_info, address) catch { - try out_stream.print("???:?:?: " ++ DIM ++ ptr_hex ++ " in ??? (???)" ++ RESET ++ "\n ???\n\n", - address); + try out_stream.print("???:?:?: " ++ DIM ++ ptr_hex ++ " in ??? (???)" ++ RESET ++ "\n ???\n\n", address); return; }; const compile_unit_name = try compile_unit.die.getAttrString(debug_info, DW.AT_name); if (getLineNumberInfo(debug_info, compile_unit, address - 1)) |line_info| { defer line_info.deinit(); - try out_stream.print(WHITE ++ "{}:{}:{}" ++ RESET ++ ": " ++ - DIM ++ ptr_hex ++ " in ??? ({})" ++ RESET ++ "\n", - line_info.file_name, line_info.line, line_info.column, - address, compile_unit_name); + try out_stream.print(WHITE ++ "{}:{}:{}" ++ RESET ++ ": " ++ DIM ++ ptr_hex ++ " in ??? ({})" ++ RESET ++ "\n", line_info.file_name, line_info.line, line_info.column, address, compile_unit_name); if (printLineFromFile(debug_info.allocator(), out_stream, line_info)) { if (line_info.column == 0) { try out_stream.write("\n"); } else { - {var col_i: usize = 1; while (col_i < line_info.column) : (col_i += 1) { - try out_stream.writeByte(' '); - }} + { + var col_i: usize = 1; + while (col_i < line_info.column) : (col_i += 1) { + try out_stream.writeByte(' '); + } + } try out_stream.write(GREEN ++ "^" ++ RESET ++ "\n"); } } else |err| switch (err) { @@ -233,7 +227,8 @@ fn printSourceAtAddress(debug_info: &ElfStackTrace, out_stream: var, address: us else => return err, } } else |err| switch (err) { - error.MissingDebugInfo, error.InvalidDebugInfo => { + error.MissingDebugInfo, + error.InvalidDebugInfo => { try out_stream.print(ptr_hex ++ " in ??? ({})\n", address, compile_unit_name); }, else => return err, @@ -247,7 +242,7 @@ pub fn openSelfDebugInfo(allocator: &mem.Allocator) !&ElfStackTrace { builtin.ObjectFormat.elf => { const st = try allocator.create(ElfStackTrace); errdefer allocator.destroy(st); - *st = ElfStackTrace { + st.* = ElfStackTrace{ .self_exe_file = undefined, .elf = undefined, .debug_info = undefined, @@ -279,9 +274,7 @@ pub fn openSelfDebugInfo(allocator: &mem.Allocator) !&ElfStackTrace { const st = try allocator.create(ElfStackTrace); errdefer allocator.destroy(st); - *st = ElfStackTrace { - .symbol_table = try macho.loadSymbols(allocator, &io.FileInStream.init(&exe_file)), - }; + st.* = ElfStackTrace{ .symbol_table = try macho.loadSymbols(allocator, &io.FileInStream.init(&exe_file)) }; return st; }, @@ -325,8 +318,7 @@ fn printLineFromFile(allocator: &mem.Allocator, out_stream: var, line_info: &con } } - if (amt_read < buf.len) - return error.EndOfFile; + if (amt_read < buf.len) return error.EndOfFile; } } @@ -418,10 +410,8 @@ const Constant = struct { signed: bool, fn asUnsignedLe(self: &const Constant) !u64 { - if (self.payload.len > @sizeOf(u64)) - return error.InvalidDebugInfo; - if (self.signed) - return error.InvalidDebugInfo; + if (self.payload.len > @sizeOf(u64)) return error.InvalidDebugInfo; + if (self.signed) return error.InvalidDebugInfo; return mem.readInt(self.payload, u64, builtin.Endian.Little); } }; @@ -438,15 +428,14 @@ const Die = struct { fn getAttr(self: &const Die, id: u64) ?&const FormValue { for (self.attrs.toSliceConst()) |*attr| { - if (attr.id == id) - return &attr.value; + if (attr.id == id) return &attr.value; } return null; } fn getAttrAddr(self: &const Die, id: u64) !u64 { const form_value = self.getAttr(id) ?? return error.MissingDebugInfo; - return switch (*form_value) { + return switch (form_value.*) { FormValue.Address => |value| value, else => error.InvalidDebugInfo, }; @@ -454,7 +443,7 @@ const Die = struct { fn getAttrSecOffset(self: &const Die, id: u64) !u64 { const form_value = self.getAttr(id) ?? return error.MissingDebugInfo; - return switch (*form_value) { + return switch (form_value.*) { FormValue.Const => |value| value.asUnsignedLe(), FormValue.SecOffset => |value| value, else => error.InvalidDebugInfo, @@ -463,7 +452,7 @@ const Die = struct { fn getAttrUnsignedLe(self: &const Die, id: u64) !u64 { const form_value = self.getAttr(id) ?? return error.MissingDebugInfo; - return switch (*form_value) { + return switch (form_value.*) { FormValue.Const => |value| value.asUnsignedLe(), else => error.InvalidDebugInfo, }; @@ -471,7 +460,7 @@ const Die = struct { fn getAttrString(self: &const Die, st: &ElfStackTrace, id: u64) ![]u8 { const form_value = self.getAttr(id) ?? return error.MissingDebugInfo; - return switch (*form_value) { + return switch (form_value.*) { FormValue.String => |value| value, FormValue.StrPtr => |offset| getString(st, offset), else => error.InvalidDebugInfo, @@ -518,10 +507,8 @@ const LineNumberProgram = struct { prev_basic_block: bool, prev_end_sequence: bool, - pub fn init(is_stmt: bool, include_dirs: []const []const u8, - file_entries: &ArrayList(FileEntry), target_address: usize) LineNumberProgram - { - return LineNumberProgram { + pub fn init(is_stmt: bool, include_dirs: []const []const u8, file_entries: &ArrayList(FileEntry), target_address: usize) LineNumberProgram { + return LineNumberProgram{ .address = 0, .file = 1, .line = 1, @@ -548,14 +535,16 @@ const LineNumberProgram = struct { return error.MissingDebugInfo; } else if (self.prev_file - 1 >= self.file_entries.len) { return error.InvalidDebugInfo; - } else &self.file_entries.items[self.prev_file - 1]; + } else + &self.file_entries.items[self.prev_file - 1]; const dir_name = if (file_entry.dir_index >= self.include_dirs.len) { return error.InvalidDebugInfo; - } else self.include_dirs[file_entry.dir_index]; + } 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); errdefer self.file_entries.allocator.free(file_name); - return LineInfo { + return LineInfo{ .line = if (self.prev_line >= 0) usize(self.prev_line) else 0, .column = self.prev_column, .file_name = file_name, @@ -578,8 +567,7 @@ fn readStringRaw(allocator: &mem.Allocator, in_stream: var) ![]u8 { var buf = ArrayList(u8).init(allocator); while (true) { const byte = try in_stream.readByte(); - if (byte == 0) - break; + if (byte == 0) break; try buf.append(byte); } return buf.toSlice(); @@ -600,7 +588,7 @@ fn readAllocBytes(allocator: &mem.Allocator, in_stream: var, size: usize) ![]u8 fn parseFormValueBlockLen(allocator: &mem.Allocator, in_stream: var, size: usize) !FormValue { const buf = try readAllocBytes(allocator, in_stream, size); - return FormValue { .Block = buf }; + return FormValue{ .Block = buf }; } fn parseFormValueBlock(allocator: &mem.Allocator, in_stream: var, size: usize) !FormValue { @@ -609,26 +597,23 @@ fn parseFormValueBlock(allocator: &mem.Allocator, in_stream: var, size: usize) ! } fn parseFormValueConstant(allocator: &mem.Allocator, in_stream: var, signed: bool, size: usize) !FormValue { - return FormValue { .Const = Constant { + return FormValue{ .Const = Constant{ .signed = signed, .payload = try readAllocBytes(allocator, in_stream, size), - }}; + } }; } fn parseFormValueDwarfOffsetSize(in_stream: var, is_64: bool) !u64 { - return if (is_64) try in_stream.readIntLe(u64) - else u64(try in_stream.readIntLe(u32)) ; + return if (is_64) try in_stream.readIntLe(u64) else u64(try in_stream.readIntLe(u32)); } fn parseFormValueTargetAddrSize(in_stream: var) !u64 { - return if (@sizeOf(usize) == 4) u64(try in_stream.readIntLe(u32)) - else if (@sizeOf(usize) == 8) try in_stream.readIntLe(u64) - else unreachable; + return if (@sizeOf(usize) == 4) u64(try in_stream.readIntLe(u32)) else if (@sizeOf(usize) == 8) try in_stream.readIntLe(u64) else unreachable; } fn parseFormValueRefLen(allocator: &mem.Allocator, in_stream: var, size: usize) !FormValue { const buf = try readAllocBytes(allocator, in_stream, size); - return FormValue { .Ref = buf }; + return FormValue{ .Ref = buf }; } fn parseFormValueRef(allocator: &mem.Allocator, in_stream: var, comptime T: type) !FormValue { @@ -646,11 +631,9 @@ const ParseFormValueError = error { OutOfMemory, }; -fn parseFormValue(allocator: &mem.Allocator, in_stream: var, form_id: u64, is_64: bool) - ParseFormValueError!FormValue -{ +fn parseFormValue(allocator: &mem.Allocator, in_stream: var, form_id: u64, is_64: bool) ParseFormValueError!FormValue { return switch (form_id) { - DW.FORM_addr => FormValue { .Address = try parseFormValueTargetAddrSize(in_stream) }, + DW.FORM_addr => FormValue{ .Address = try parseFormValueTargetAddrSize(in_stream) }, DW.FORM_block1 => parseFormValueBlock(allocator, in_stream, 1), DW.FORM_block2 => parseFormValueBlock(allocator, in_stream, 2), DW.FORM_block4 => parseFormValueBlock(allocator, in_stream, 4), @@ -662,7 +645,8 @@ fn parseFormValue(allocator: &mem.Allocator, in_stream: var, form_id: u64, is_64 DW.FORM_data2 => parseFormValueConstant(allocator, in_stream, false, 2), DW.FORM_data4 => parseFormValueConstant(allocator, in_stream, false, 4), DW.FORM_data8 => parseFormValueConstant(allocator, in_stream, false, 8), - DW.FORM_udata, DW.FORM_sdata => { + DW.FORM_udata, + DW.FORM_sdata => { const block_len = try readULeb128(in_stream); const signed = form_id == DW.FORM_sdata; return parseFormValueConstant(allocator, in_stream, signed, block_len); @@ -670,11 +654,11 @@ fn parseFormValue(allocator: &mem.Allocator, in_stream: var, form_id: u64, is_64 DW.FORM_exprloc => { const size = try readULeb128(in_stream); const buf = try readAllocBytes(allocator, in_stream, size); - return FormValue { .ExprLoc = buf }; + return FormValue{ .ExprLoc = buf }; }, - DW.FORM_flag => FormValue { .Flag = (try in_stream.readByte()) != 0 }, - DW.FORM_flag_present => FormValue { .Flag = true }, - DW.FORM_sec_offset => FormValue { .SecOffset = try parseFormValueDwarfOffsetSize(in_stream, is_64) }, + DW.FORM_flag => FormValue{ .Flag = (try in_stream.readByte()) != 0 }, + DW.FORM_flag_present => FormValue{ .Flag = true }, + DW.FORM_sec_offset => FormValue{ .SecOffset = try parseFormValueDwarfOffsetSize(in_stream, is_64) }, DW.FORM_ref1 => parseFormValueRef(allocator, in_stream, u8), DW.FORM_ref2 => parseFormValueRef(allocator, in_stream, u16), @@ -685,11 +669,11 @@ fn parseFormValue(allocator: &mem.Allocator, in_stream: var, form_id: u64, is_64 return parseFormValueRefLen(allocator, in_stream, ref_len); }, - DW.FORM_ref_addr => FormValue { .RefAddr = try parseFormValueDwarfOffsetSize(in_stream, is_64) }, - DW.FORM_ref_sig8 => FormValue { .RefSig8 = try in_stream.readIntLe(u64) }, + DW.FORM_ref_addr => FormValue{ .RefAddr = try parseFormValueDwarfOffsetSize(in_stream, is_64) }, + DW.FORM_ref_sig8 => FormValue{ .RefSig8 = try in_stream.readIntLe(u64) }, - DW.FORM_string => FormValue { .String = try readStringRaw(allocator, in_stream) }, - DW.FORM_strp => FormValue { .StrPtr = try parseFormValueDwarfOffsetSize(in_stream, is_64) }, + DW.FORM_string => FormValue{ .String = try readStringRaw(allocator, in_stream) }, + DW.FORM_strp => FormValue{ .StrPtr = try parseFormValueDwarfOffsetSize(in_stream, is_64) }, DW.FORM_indirect => { const child_form_id = try readULeb128(in_stream); return parseFormValue(allocator, in_stream, child_form_id, is_64); @@ -705,9 +689,8 @@ fn parseAbbrevTable(st: &ElfStackTrace) !AbbrevTable { var result = AbbrevTable.init(st.allocator()); while (true) { const abbrev_code = try readULeb128(in_stream); - if (abbrev_code == 0) - return result; - try result.append(AbbrevTableEntry { + if (abbrev_code == 0) return result; + try result.append(AbbrevTableEntry{ .abbrev_code = abbrev_code, .tag_id = try readULeb128(in_stream), .has_children = (try in_stream.readByte()) == DW.CHILDREN_yes, @@ -718,9 +701,8 @@ fn parseAbbrevTable(st: &ElfStackTrace) !AbbrevTable { while (true) { const attr_id = try readULeb128(in_stream); const form_id = try readULeb128(in_stream); - if (attr_id == 0 and form_id == 0) - break; - try attrs.append(AbbrevAttr { + if (attr_id == 0 and form_id == 0) break; + try attrs.append(AbbrevAttr{ .attr_id = attr_id, .form_id = form_id, }); @@ -737,7 +719,7 @@ fn getAbbrevTable(st: &ElfStackTrace, abbrev_offset: u64) !&const AbbrevTable { } } try st.self_exe_file.seekTo(st.debug_abbrev.offset + abbrev_offset); - try st.abbrev_table_list.append(AbbrevTableHeader { + try st.abbrev_table_list.append(AbbrevTableHeader{ .offset = abbrev_offset, .table = try parseAbbrevTable(st), }); @@ -746,8 +728,7 @@ fn getAbbrevTable(st: &ElfStackTrace, abbrev_offset: u64) !&const AbbrevTable { fn getAbbrevTableEntry(abbrev_table: &const AbbrevTable, abbrev_code: u64) ?&const AbbrevTableEntry { for (abbrev_table.toSliceConst()) |*table_entry| { - if (table_entry.abbrev_code == abbrev_code) - return table_entry; + if (table_entry.abbrev_code == abbrev_code) return table_entry; } return null; } @@ -759,14 +740,14 @@ fn parseDie(st: &ElfStackTrace, abbrev_table: &const AbbrevTable, is_64: bool) ! const abbrev_code = try readULeb128(in_stream); const table_entry = getAbbrevTableEntry(abbrev_table, abbrev_code) ?? return error.InvalidDebugInfo; - var result = Die { + var result = Die{ .tag_id = table_entry.tag_id, .has_children = table_entry.has_children, .attrs = ArrayList(Die.Attr).init(st.allocator()), }; try result.attrs.resize(table_entry.attrs.len); for (table_entry.attrs.toSliceConst()) |attr, i| { - result.attrs.items[i] = Die.Attr { + result.attrs.items[i] = Die.Attr{ .id = attr.attr_id, .value = try parseFormValue(st.allocator(), in_stream, attr.form_id, is_64), }; @@ -790,8 +771,7 @@ fn getLineNumberInfo(st: &ElfStackTrace, compile_unit: &const CompileUnit, targe var is_64: bool = undefined; const unit_length = try readInitialLength(@typeOf(in_stream.readFn).ReturnType.ErrorSet, in_stream, &is_64); - if (unit_length == 0) - return error.MissingDebugInfo; + if (unit_length == 0) return error.MissingDebugInfo; const next_offset = unit_length + (if (is_64) usize(12) else usize(4)); if (compile_unit.index != this_index) { @@ -803,8 +783,7 @@ fn getLineNumberInfo(st: &ElfStackTrace, compile_unit: &const CompileUnit, targe // TODO support 3 and 5 if (version != 2 and version != 4) return error.InvalidDebugInfo; - const prologue_length = if (is_64) try in_stream.readInt(st.elf.endian, u64) - else try in_stream.readInt(st.elf.endian, u32); + const prologue_length = if (is_64) try in_stream.readInt(st.elf.endian, u64) else try in_stream.readInt(st.elf.endian, u32); const prog_start_offset = (try in_file.getPos()) + prologue_length; const minimum_instruction_length = try in_stream.readByte(); @@ -819,38 +798,37 @@ fn getLineNumberInfo(st: &ElfStackTrace, compile_unit: &const CompileUnit, targe const line_base = try in_stream.readByteSigned(); const line_range = try in_stream.readByte(); - if (line_range == 0) - return error.InvalidDebugInfo; + if (line_range == 0) return error.InvalidDebugInfo; const opcode_base = try in_stream.readByte(); const standard_opcode_lengths = try st.allocator().alloc(u8, opcode_base - 1); - {var i: usize = 0; while (i < opcode_base - 1) : (i += 1) { - standard_opcode_lengths[i] = try in_stream.readByte(); - }} + { + var i: usize = 0; + while (i < opcode_base - 1) : (i += 1) { + standard_opcode_lengths[i] = try in_stream.readByte(); + } + } var include_directories = ArrayList([]u8).init(st.allocator()); try include_directories.append(compile_unit_cwd); while (true) { const dir = try st.readString(); - if (dir.len == 0) - break; + if (dir.len == 0) break; try include_directories.append(dir); } var file_entries = ArrayList(FileEntry).init(st.allocator()); - var prog = LineNumberProgram.init(default_is_stmt, include_directories.toSliceConst(), - &file_entries, target_address); + var prog = LineNumberProgram.init(default_is_stmt, include_directories.toSliceConst(), &file_entries, target_address); while (true) { const file_name = try st.readString(); - if (file_name.len == 0) - break; + if (file_name.len == 0) break; const dir_index = try readULeb128(in_stream); const mtime = try readULeb128(in_stream); const len_bytes = try readULeb128(in_stream); - try file_entries.append(FileEntry { + try file_entries.append(FileEntry{ .file_name = file_name, .dir_index = dir_index, .mtime = mtime, @@ -866,8 +844,7 @@ fn getLineNumberInfo(st: &ElfStackTrace, compile_unit: &const CompileUnit, targe var sub_op: u8 = undefined; // TODO move this to the correct scope and fix the compiler crash if (opcode == DW.LNS_extended_op) { const op_size = try readULeb128(in_stream); - if (op_size < 1) - return error.InvalidDebugInfo; + if (op_size < 1) return error.InvalidDebugInfo; sub_op = try in_stream.readByte(); switch (sub_op) { DW.LNE_end_sequence => { @@ -884,7 +861,7 @@ fn getLineNumberInfo(st: &ElfStackTrace, compile_unit: &const CompileUnit, targe const dir_index = try readULeb128(in_stream); const mtime = try readULeb128(in_stream); const len_bytes = try readULeb128(in_stream); - try file_entries.append(FileEntry { + try file_entries.append(FileEntry{ .file_name = file_name, .dir_index = dir_index, .mtime = mtime, @@ -941,11 +918,9 @@ fn getLineNumberInfo(st: &ElfStackTrace, compile_unit: &const CompileUnit, targe const arg = try in_stream.readInt(st.elf.endian, u16); prog.address += arg; }, - DW.LNS_set_prologue_end => { - }, + DW.LNS_set_prologue_end => {}, else => { - if (opcode - 1 >= standard_opcode_lengths.len) - return error.InvalidDebugInfo; + if (opcode - 1 >= standard_opcode_lengths.len) return error.InvalidDebugInfo; const len_bytes = standard_opcode_lengths[opcode - 1]; try in_file.seekForward(len_bytes); }, @@ -972,16 +947,13 @@ fn scanAllCompileUnits(st: &ElfStackTrace) !void { var is_64: bool = undefined; const unit_length = try readInitialLength(@typeOf(in_stream.readFn).ReturnType.ErrorSet, in_stream, &is_64); - if (unit_length == 0) - return; + if (unit_length == 0) return; const next_offset = unit_length + (if (is_64) usize(12) else usize(4)); const version = try in_stream.readInt(st.elf.endian, u16); if (version < 2 or version > 5) return error.InvalidDebugInfo; - const debug_abbrev_offset = - if (is_64) try in_stream.readInt(st.elf.endian, u64) - else try in_stream.readInt(st.elf.endian, u32); + const debug_abbrev_offset = if (is_64) try in_stream.readInt(st.elf.endian, u64) else try in_stream.readInt(st.elf.endian, u32); const address_size = try in_stream.readByte(); if (address_size != @sizeOf(usize)) return error.InvalidDebugInfo; @@ -992,15 +964,14 @@ fn scanAllCompileUnits(st: &ElfStackTrace) !void { try st.self_exe_file.seekTo(compile_unit_pos); const compile_unit_die = try st.allocator().create(Die); - *compile_unit_die = try parseDie(st, abbrev_table, is_64); + compile_unit_die.* = try parseDie(st, abbrev_table, is_64); - if (compile_unit_die.tag_id != DW.TAG_compile_unit) - return error.InvalidDebugInfo; + if (compile_unit_die.tag_id != DW.TAG_compile_unit) return error.InvalidDebugInfo; const pc_range = x: { if (compile_unit_die.getAttrAddr(DW.AT_low_pc)) |low_pc| { if (compile_unit_die.getAttr(DW.AT_high_pc)) |high_pc_value| { - const pc_end = switch (*high_pc_value) { + const pc_end = switch (high_pc_value.*) { FormValue.Address => |value| value, FormValue.Const => |value| b: { const offset = try value.asUnsignedLe(); @@ -1008,7 +979,7 @@ fn scanAllCompileUnits(st: &ElfStackTrace) !void { }, else => return error.InvalidDebugInfo, }; - break :x PcRange { + break :x PcRange{ .start = low_pc, .end = pc_end, }; @@ -1016,13 +987,12 @@ fn scanAllCompileUnits(st: &ElfStackTrace) !void { break :x null; } } else |err| { - if (err != error.MissingDebugInfo) - return err; + if (err != error.MissingDebugInfo) return err; break :x null; } }; - try st.compile_unit_list.append(CompileUnit { + try st.compile_unit_list.append(CompileUnit{ .version = version, .is_64 = is_64, .pc_range = pc_range, @@ -1040,8 +1010,7 @@ fn findCompileUnit(st: &ElfStackTrace, target_address: u64) !&const CompileUnit const in_stream = &in_file_stream.stream; for (st.compile_unit_list.toSlice()) |*compile_unit| { if (compile_unit.pc_range) |range| { - if (target_address >= range.start and target_address < range.end) - return compile_unit; + if (target_address >= range.start and target_address < range.end) return compile_unit; } if (compile_unit.die.getAttrSecOffset(DW.AT_ranges)) |ranges_offset| { var base_address: usize = 0; @@ -1063,8 +1032,7 @@ fn findCompileUnit(st: &ElfStackTrace, target_address: u64) !&const CompileUnit } } } else |err| { - if (err != error.MissingDebugInfo) - return err; + if (err != error.MissingDebugInfo) return err; continue; } } @@ -1073,8 +1041,8 @@ fn findCompileUnit(st: &ElfStackTrace, target_address: u64) !&const CompileUnit fn readInitialLength(comptime E: type, in_stream: &io.InStream(E), is_64: &bool) !u64 { const first_32_bits = try in_stream.readIntLe(u32); - *is_64 = (first_32_bits == 0xffffffff); - if (*is_64) { + is_64.* = (first_32_bits == 0xffffffff); + if (is_64.*) { return in_stream.readIntLe(u64); } else { if (first_32_bits >= 0xfffffff0) return error.InvalidDebugInfo; @@ -1091,13 +1059,11 @@ fn readULeb128(in_stream: var) !u64 { var operand: u64 = undefined; - if (@shlWithOverflow(u64, byte & 0b01111111, u6(shift), &operand)) - return error.InvalidDebugInfo; + if (@shlWithOverflow(u64, byte & 0b01111111, u6(shift), &operand)) return error.InvalidDebugInfo; result |= operand; - if ((byte & 0b10000000) == 0) - return result; + if ((byte & 0b10000000) == 0) return result; shift += 7; } @@ -1112,15 +1078,13 @@ fn readILeb128(in_stream: var) !i64 { var operand: i64 = undefined; - if (@shlWithOverflow(i64, byte & 0b01111111, u6(shift), &operand)) - return error.InvalidDebugInfo; + if (@shlWithOverflow(i64, byte & 0b01111111, u6(shift), &operand)) return error.InvalidDebugInfo; result |= operand; shift += 7; if ((byte & 0b10000000) == 0) { - if (shift < @sizeOf(i64) * 8 and (byte & 0b01000000) != 0) - result |= -(i64(1) << u6(shift)); + if (shift < @sizeOf(i64) * 8 and (byte & 0b01000000) != 0) result |= -(i64(1) << u6(shift)); return result; } } @@ -1131,7 +1095,6 @@ pub const global_allocator = &global_fixed_allocator.allocator; var global_fixed_allocator = std.heap.FixedBufferAllocator.init(global_allocator_mem[0..]); var global_allocator_mem: [100 * 1024]u8 = undefined; - // TODO make thread safe var debug_info_allocator: ?&mem.Allocator = null; var debug_info_direct_allocator: std.heap.DirectAllocator = undefined; diff --git a/std/math/index.zig b/std/math/index.zig index 83ba055329e584e5fed82da09e8a5e2d5aad65f2..05de604c6ce2db46a542c94adec9b13570a0dea3 100644 --- a/std/math/index.zig +++ b/std/math/index.zig @@ -47,12 +47,12 @@ pub fn forceEval(value: var) void { f32 => { var x: f32 = undefined; const p = @ptrCast(&volatile f32, &x); - *p = x; + p.* = x; }, f64 => { var x: f64 = undefined; const p = @ptrCast(&volatile f64, &x); - *p = x; + p.* = x; }, else => { @compileError("forceEval not implemented for " ++ @typeName(T)); @@ -179,7 +179,6 @@ test "math" { _ = @import("complex/index.zig"); } - pub fn min(x: var, y: var) @typeOf(x + y) { return if (x < y) x else y; } @@ -280,10 +279,10 @@ pub fn rotr(comptime T: type, x: T, r: var) T { } test "math.rotr" { - assert(rotr(u8, 0b00000001, usize(0)) == 0b00000001); - assert(rotr(u8, 0b00000001, usize(9)) == 0b10000000); - assert(rotr(u8, 0b00000001, usize(8)) == 0b00000001); - assert(rotr(u8, 0b00000001, usize(4)) == 0b00010000); + assert(rotr(u8, 0b00000001, usize(0)) == 0b00000001); + assert(rotr(u8, 0b00000001, usize(9)) == 0b10000000); + assert(rotr(u8, 0b00000001, usize(8)) == 0b00000001); + assert(rotr(u8, 0b00000001, usize(4)) == 0b00010000); assert(rotr(u8, 0b00000001, isize(-1)) == 0b00000010); } @@ -299,14 +298,13 @@ pub fn rotl(comptime T: type, x: T, r: var) T { } test "math.rotl" { - assert(rotl(u8, 0b00000001, usize(0)) == 0b00000001); - assert(rotl(u8, 0b00000001, usize(9)) == 0b00000010); - assert(rotl(u8, 0b00000001, usize(8)) == 0b00000001); - assert(rotl(u8, 0b00000001, usize(4)) == 0b00010000); + assert(rotl(u8, 0b00000001, usize(0)) == 0b00000001); + assert(rotl(u8, 0b00000001, usize(9)) == 0b00000010); + assert(rotl(u8, 0b00000001, usize(8)) == 0b00000001); + assert(rotl(u8, 0b00000001, usize(4)) == 0b00010000); assert(rotl(u8, 0b00000001, isize(-1)) == 0b10000000); } - pub fn Log2Int(comptime T: type) type { return @IntType(false, log2(T.bit_count)); } @@ -323,14 +321,14 @@ fn testOverflow() void { assert((shlExact(i32, 0b11, 4) catch unreachable) == 0b110000); } - pub fn absInt(x: var) !@typeOf(x) { const T = @typeOf(x); comptime assert(@typeId(T) == builtin.TypeId.Int); // must pass an integer to absInt comptime assert(T.is_signed); // must pass a signed integer to absInt - if (x == @minValue(@typeOf(x))) + + if (x == @minValue(@typeOf(x))) { return error.Overflow; - { + } else { @setRuntimeSafety(false); return if (x < 0) -x else x; } @@ -349,10 +347,8 @@ pub const absFloat = @import("fabs.zig").fabs; pub fn divTrunc(comptime T: type, numerator: T, denominator: T) !T { @setRuntimeSafety(false); - if (denominator == 0) - return error.DivisionByZero; - if (@typeId(T) == builtin.TypeId.Int and T.is_signed and numerator == @minValue(T) and denominator == -1) - return error.Overflow; + if (denominator == 0) return error.DivisionByZero; + if (@typeId(T) == builtin.TypeId.Int and T.is_signed and numerator == @minValue(T) and denominator == -1) return error.Overflow; return @divTrunc(numerator, denominator); } @@ -372,10 +368,8 @@ fn testDivTrunc() void { pub fn divFloor(comptime T: type, numerator: T, denominator: T) !T { @setRuntimeSafety(false); - if (denominator == 0) - return error.DivisionByZero; - if (@typeId(T) == builtin.TypeId.Int and T.is_signed and numerator == @minValue(T) and denominator == -1) - return error.Overflow; + if (denominator == 0) return error.DivisionByZero; + if (@typeId(T) == builtin.TypeId.Int and T.is_signed and numerator == @minValue(T) and denominator == -1) return error.Overflow; return @divFloor(numerator, denominator); } @@ -395,13 +389,10 @@ fn testDivFloor() void { pub fn divExact(comptime T: type, numerator: T, denominator: T) !T { @setRuntimeSafety(false); - if (denominator == 0) - return error.DivisionByZero; - if (@typeId(T) == builtin.TypeId.Int and T.is_signed and numerator == @minValue(T) and denominator == -1) - return error.Overflow; + if (denominator == 0) return error.DivisionByZero; + if (@typeId(T) == builtin.TypeId.Int and T.is_signed and numerator == @minValue(T) and denominator == -1) return error.Overflow; const result = @divTrunc(numerator, denominator); - if (result * denominator != numerator) - return error.UnexpectedRemainder; + if (result * denominator != numerator) return error.UnexpectedRemainder; return result; } @@ -423,10 +414,8 @@ fn testDivExact() void { pub fn mod(comptime T: type, numerator: T, denominator: T) !T { @setRuntimeSafety(false); - if (denominator == 0) - return error.DivisionByZero; - if (denominator < 0) - return error.NegativeDenominator; + if (denominator == 0) return error.DivisionByZero; + if (denominator < 0) return error.NegativeDenominator; return @mod(numerator, denominator); } @@ -448,10 +437,8 @@ fn testMod() void { pub fn rem(comptime T: type, numerator: T, denominator: T) !T { @setRuntimeSafety(false); - if (denominator == 0) - return error.DivisionByZero; - if (denominator < 0) - return error.NegativeDenominator; + if (denominator == 0) return error.DivisionByZero; + if (denominator < 0) return error.NegativeDenominator; return @rem(numerator, denominator); } @@ -475,8 +462,7 @@ fn testRem() void { /// Result is an unsigned integer. pub fn absCast(x: var) @IntType(false, @typeOf(x).bit_count) { const uint = @IntType(false, @typeOf(x).bit_count); - if (x >= 0) - return uint(x); + if (x >= 0) return uint(x); return uint(-(x + 1)) + 1; } @@ -495,15 +481,12 @@ test "math.absCast" { /// Returns the negation of the integer parameter. /// Result is a signed integer. pub fn negateCast(x: var) !@IntType(true, @typeOf(x).bit_count) { - if (@typeOf(x).is_signed) - return negate(x); + if (@typeOf(x).is_signed) return negate(x); const int = @IntType(true, @typeOf(x).bit_count); - if (x > -@minValue(int)) - return error.Overflow; + if (x > -@minValue(int)) return error.Overflow; - if (x == -@minValue(int)) - return @minValue(int); + if (x == -@minValue(int)) return @minValue(int); return -int(x); } @@ -546,7 +529,7 @@ pub fn floorPowerOfTwo(comptime T: type, value: T) T { var x = value; comptime var i = 1; - inline while(T.bit_count > i) : (i *= 2) { + inline while (T.bit_count > i) : (i *= 2) { x |= (x >> i); } diff --git a/std/mem.zig b/std/mem.zig index d874f8a6c98d659681e25efb811e68045f4d666b..3ca87b35d39ce526e048ea5244ce119d7a5f1bd9 100644 --- a/std/mem.zig +++ b/std/mem.zig @@ -6,14 +6,14 @@ const builtin = @import("builtin"); const mem = this; pub const Allocator = struct { - const Error = error {OutOfMemory}; + const Error = error{OutOfMemory}; /// Allocate byte_count bytes and return them in a slice, with the /// slice's pointer aligned at least to alignment bytes. /// The returned newly allocated memory is undefined. /// `alignment` is guaranteed to be >= 1 /// `alignment` is guaranteed to be a power of 2 - allocFn: fn (self: &Allocator, byte_count: usize, alignment: u29) Error![]u8, + allocFn: fn(self: &Allocator, byte_count: usize, alignment: u29) Error![]u8, /// If `new_byte_count > old_mem.len`: /// * `old_mem.len` is the same as what was returned from allocFn or reallocFn. @@ -26,10 +26,10 @@ pub const Allocator = struct { /// The returned newly allocated memory is undefined. /// `alignment` is guaranteed to be >= 1 /// `alignment` is guaranteed to be a power of 2 - reallocFn: fn (self: &Allocator, old_mem: []u8, new_byte_count: usize, alignment: u29) Error![]u8, + reallocFn: fn(self: &Allocator, old_mem: []u8, new_byte_count: usize, alignment: u29) Error![]u8, /// Guaranteed: `old_mem.len` is the same as what was returned from `allocFn` or `reallocFn` - freeFn: fn (self: &Allocator, old_mem: []u8) void, + freeFn: fn(self: &Allocator, old_mem: []u8) void, fn create(self: &Allocator, comptime T: type) !&T { if (@sizeOf(T) == 0) return &{}; @@ -47,7 +47,7 @@ pub const Allocator = struct { if (@sizeOf(T) == 0) return &{}; const slice = try self.alloc(T, 1); const ptr = &slice[0]; - *ptr = *init; + ptr.* = init.*; return ptr; } @@ -59,9 +59,7 @@ pub const Allocator = struct { return self.alignedAlloc(T, @alignOf(T), n); } - fn alignedAlloc(self: &Allocator, comptime T: type, comptime alignment: u29, - n: usize) ![]align(alignment) T - { + fn alignedAlloc(self: &Allocator, comptime T: type, comptime alignment: u29, n: usize) ![]align(alignment) T { if (n == 0) { return (&align(alignment) T)(undefined)[0..0]; } @@ -70,7 +68,7 @@ pub const Allocator = struct { assert(byte_slice.len == byte_count); // This loop gets optimized out in ReleaseFast mode for (byte_slice) |*byte| { - *byte = undefined; + byte.* = undefined; } return ([]align(alignment) T)(@alignCast(alignment, byte_slice)); } @@ -79,9 +77,7 @@ pub const Allocator = struct { return self.alignedRealloc(T, @alignOf(T), @alignCast(@alignOf(T), old_mem), n); } - fn alignedRealloc(self: &Allocator, comptime T: type, comptime alignment: u29, - old_mem: []align(alignment) T, n: usize) ![]align(alignment) T - { + fn alignedRealloc(self: &Allocator, comptime T: type, comptime alignment: u29, old_mem: []align(alignment) T, n: usize) ![]align(alignment) T { if (old_mem.len == 0) { return self.alloc(T, n); } @@ -97,7 +93,7 @@ pub const Allocator = struct { if (n > old_mem.len) { // This loop gets optimized out in ReleaseFast mode for (byte_slice[old_byte_slice.len..]) |*byte| { - *byte = undefined; + byte.* = undefined; } } return ([]T)(@alignCast(alignment, byte_slice)); @@ -110,9 +106,7 @@ pub const Allocator = struct { return self.alignedShrink(T, @alignOf(T), @alignCast(@alignOf(T), old_mem), n); } - fn alignedShrink(self: &Allocator, comptime T: type, comptime alignment: u29, - old_mem: []align(alignment) T, n: usize) []align(alignment) T - { + fn alignedShrink(self: &Allocator, comptime T: type, comptime alignment: u29, old_mem: []align(alignment) T, n: usize) []align(alignment) T { if (n == 0) { self.free(old_mem); return old_mem[0..0]; @@ -131,8 +125,7 @@ pub const Allocator = struct { fn free(self: &Allocator, memory: var) void { const bytes = ([]const u8)(memory); - if (bytes.len == 0) - return; + if (bytes.len == 0) return; const non_const_ptr = @intToPtr(&u8, @ptrToInt(bytes.ptr)); self.freeFn(self, non_const_ptr[0..bytes.len]); } @@ -146,11 +139,13 @@ pub fn copy(comptime T: type, dest: []T, source: []const T) void { // this and automatically omit safety checks for loops @setRuntimeSafety(false); assert(dest.len >= source.len); - for (source) |s, i| dest[i] = s; + for (source) |s, i| + dest[i] = s; } pub fn set(comptime T: type, dest: []T, value: T) void { - for (dest) |*d| *d = value; + for (dest) |*d| + d.* = value; } /// Returns true if lhs < rhs, false otherwise @@ -229,8 +224,7 @@ pub fn lastIndexOfScalar(comptime T: type, slice: []const T, value: T) ?usize { var i: usize = slice.len; while (i != 0) { i -= 1; - if (slice[i] == value) - return i; + if (slice[i] == value) return i; } return null; } @@ -238,8 +232,7 @@ pub fn lastIndexOfScalar(comptime T: type, slice: []const T, value: T) ?usize { pub fn indexOfScalarPos(comptime T: type, slice: []const T, start_index: usize, value: T) ?usize { var i: usize = start_index; while (i < slice.len) : (i += 1) { - if (slice[i] == value) - return i; + if (slice[i] == value) return i; } return null; } @@ -253,8 +246,7 @@ pub fn lastIndexOfAny(comptime T: type, slice: []const T, values: []const T) ?us while (i != 0) { i -= 1; for (values) |value| { - if (slice[i] == value) - return i; + if (slice[i] == value) return i; } } return null; @@ -264,8 +256,7 @@ pub fn indexOfAnyPos(comptime T: type, slice: []const T, start_index: usize, val var i: usize = start_index; while (i < slice.len) : (i += 1) { for (values) |value| { - if (slice[i] == value) - return i; + if (slice[i] == value) return i; } } return null; @@ -279,28 +270,23 @@ pub fn indexOf(comptime T: type, haystack: []const T, needle: []const T) ?usize /// To start looking at a different index, slice the haystack first. /// TODO is there even a better algorithm for this? pub fn lastIndexOf(comptime T: type, haystack: []const T, needle: []const T) ?usize { - if (needle.len > haystack.len) - return null; + if (needle.len > haystack.len) return null; var i: usize = haystack.len - needle.len; while (true) : (i -= 1) { - if (mem.eql(T, haystack[i..i+needle.len], needle)) - return i; - if (i == 0) - return null; + if (mem.eql(T, haystack[i..i + needle.len], needle)) return i; + if (i == 0) return null; } } // TODO boyer-moore algorithm pub fn indexOfPos(comptime T: type, haystack: []const T, start_index: usize, needle: []const T) ?usize { - if (needle.len > haystack.len) - return null; + if (needle.len > haystack.len) return null; var i: usize = start_index; const end = haystack.len - needle.len; while (i <= end) : (i += 1) { - if (eql(T, haystack[i .. i + needle.len], needle)) - return i; + if (eql(T, haystack[i..i + needle.len], needle)) return i; } return null; } @@ -355,9 +341,12 @@ pub fn readIntBE(comptime T: type, bytes: []const u8) T { } assert(bytes.len == @sizeOf(T)); var result: T = 0; - {comptime var i = 0; inline while (i < @sizeOf(T)) : (i += 1) { - result = (result << 8) | T(bytes[i]); - }} + { + comptime var i = 0; + inline while (i < @sizeOf(T)) : (i += 1) { + result = (result << 8) | T(bytes[i]); + } + } return result; } @@ -369,9 +358,12 @@ pub fn readIntLE(comptime T: type, bytes: []const u8) T { } assert(bytes.len == @sizeOf(T)); var result: T = 0; - {comptime var i = 0; inline while (i < @sizeOf(T)) : (i += 1) { - result |= T(bytes[i]) << i * 8; - }} + { + comptime var i = 0; + inline while (i < @sizeOf(T)) : (i += 1) { + result |= T(bytes[i]) << i * 8; + } + } return result; } @@ -393,7 +385,7 @@ pub fn writeInt(buf: []u8, value: var, endian: builtin.Endian) void { }, builtin.Endian.Little => { for (buf) |*b| { - *b = @truncate(u8, bits); + b.* = @truncate(u8, bits); bits >>= 8; } }, @@ -401,7 +393,6 @@ pub fn writeInt(buf: []u8, value: var, endian: builtin.Endian) void { assert(bits == 0); } - pub fn hash_slice_u8(k: []const u8) u32 { // FNV 32-bit hash var h: u32 = 2166136261; @@ -420,7 +411,7 @@ pub fn eql_slice_u8(a: []const u8, b: []const u8) bool { /// split(" abc def ghi ", " ") /// Will return slices for "abc", "def", "ghi", null, in that order. pub fn split(buffer: []const u8, split_bytes: []const u8) SplitIterator { - return SplitIterator { + return SplitIterator{ .index = 0, .buffer = buffer, .split_bytes = split_bytes, @@ -436,7 +427,7 @@ test "mem.split" { } pub fn startsWith(comptime T: type, haystack: []const T, needle: []const T) bool { - return if (needle.len > haystack.len) false else eql(T, haystack[0 .. needle.len], needle); + return if (needle.len > haystack.len) false else eql(T, haystack[0..needle.len], needle); } test "mem.startsWith" { @@ -445,10 +436,9 @@ test "mem.startsWith" { } pub fn endsWith(comptime T: type, haystack: []const T, needle: []const T) bool { - return if (needle.len > haystack.len) false else eql(T, haystack[haystack.len - needle.len ..], needle); + return if (needle.len > haystack.len) false else eql(T, haystack[haystack.len - needle.len..], needle); } - test "mem.endsWith" { assert(endsWith(u8, "Needle in haystack", "haystack")); assert(!endsWith(u8, "Bob", "Bo")); @@ -542,29 +532,47 @@ test "testReadInt" { } fn testReadIntImpl() void { { - const bytes = []u8{ 0x12, 0x34, 0x56, 0x78 }; - assert(readInt(bytes, u32, builtin.Endian.Big) == 0x12345678); - assert(readIntBE(u32, bytes) == 0x12345678); - assert(readIntBE(i32, bytes) == 0x12345678); + const bytes = []u8{ + 0x12, + 0x34, + 0x56, + 0x78, + }; + assert(readInt(bytes, u32, builtin.Endian.Big) == 0x12345678); + assert(readIntBE(u32, bytes) == 0x12345678); + assert(readIntBE(i32, bytes) == 0x12345678); assert(readInt(bytes, u32, builtin.Endian.Little) == 0x78563412); - assert(readIntLE(u32, bytes) == 0x78563412); - assert(readIntLE(i32, bytes) == 0x78563412); + assert(readIntLE(u32, bytes) == 0x78563412); + assert(readIntLE(i32, bytes) == 0x78563412); } { - const buf = []u8{0x00, 0x00, 0x12, 0x34}; + const buf = []u8{ + 0x00, + 0x00, + 0x12, + 0x34, + }; const answer = readInt(buf, u64, builtin.Endian.Big); assert(answer == 0x00001234); } { - const buf = []u8{0x12, 0x34, 0x00, 0x00}; + const buf = []u8{ + 0x12, + 0x34, + 0x00, + 0x00, + }; const answer = readInt(buf, u64, builtin.Endian.Little); assert(answer == 0x00003412); } { - const bytes = []u8{0xff, 0xfe}; - assert(readIntBE(u16, bytes) == 0xfffe); + const bytes = []u8{ + 0xff, + 0xfe, + }; + assert(readIntBE(u16, bytes) == 0xfffe); assert(readIntBE(i16, bytes) == -0x0002); - assert(readIntLE(u16, bytes) == 0xfeff); + assert(readIntLE(u16, bytes) == 0xfeff); assert(readIntLE(i16, bytes) == -0x0101); } } @@ -577,19 +585,38 @@ fn testWriteIntImpl() void { var bytes: [4]u8 = undefined; writeInt(bytes[0..], u32(0x12345678), builtin.Endian.Big); - assert(eql(u8, bytes, []u8{ 0x12, 0x34, 0x56, 0x78 })); + assert(eql(u8, bytes, []u8{ + 0x12, + 0x34, + 0x56, + 0x78, + })); writeInt(bytes[0..], u32(0x78563412), builtin.Endian.Little); - assert(eql(u8, bytes, []u8{ 0x12, 0x34, 0x56, 0x78 })); + assert(eql(u8, bytes, []u8{ + 0x12, + 0x34, + 0x56, + 0x78, + })); writeInt(bytes[0..], u16(0x1234), builtin.Endian.Big); - assert(eql(u8, bytes, []u8{ 0x00, 0x00, 0x12, 0x34 })); + assert(eql(u8, bytes, []u8{ + 0x00, + 0x00, + 0x12, + 0x34, + })); writeInt(bytes[0..], u16(0x1234), builtin.Endian.Little); - assert(eql(u8, bytes, []u8{ 0x34, 0x12, 0x00, 0x00 })); + assert(eql(u8, bytes, []u8{ + 0x34, + 0x12, + 0x00, + 0x00, + })); } - pub fn min(comptime T: type, slice: []const T) T { var best = slice[0]; for (slice[1..]) |item| { @@ -615,9 +642,9 @@ test "mem.max" { } pub fn swap(comptime T: type, a: &T, b: &T) void { - const tmp = *a; - *a = *b; - *b = tmp; + const tmp = a.*; + a.* = b.*; + b.* = tmp; } /// In-place order reversal of a slice @@ -630,10 +657,22 @@ pub fn reverse(comptime T: type, items: []T) void { } test "std.mem.reverse" { - var arr = []i32{ 5, 3, 1, 2, 4 }; + var arr = []i32{ + 5, + 3, + 1, + 2, + 4, + }; reverse(i32, arr[0..]); - assert(eql(i32, arr, []i32{ 4, 2, 1, 3, 5 })); + assert(eql(i32, arr, []i32{ + 4, + 2, + 1, + 3, + 5, + })); } /// In-place rotation of the values in an array ([0 1 2 3] becomes [1 2 3 0] if we rotate by 1) @@ -645,10 +684,22 @@ pub fn rotate(comptime T: type, items: []T, amount: usize) void { } test "std.mem.rotate" { - var arr = []i32{ 5, 3, 1, 2, 4 }; + var arr = []i32{ + 5, + 3, + 1, + 2, + 4, + }; rotate(i32, arr[0..], 2); - assert(eql(i32, arr, []i32{ 1, 2, 4, 5, 3 })); + assert(eql(i32, arr, []i32{ + 1, + 2, + 4, + 5, + 3, + })); } // TODO: When https://github.com/zig-lang/zig/issues/649 is solved these can be done by diff --git a/std/zig/parser.zig b/std/zig/parser.zig index b5849c3e96df6d4921b451ec0b5fa7594d6cd8ca..79a38f00ee184fada364de5f826d6ba99d829f8d 100644 --- a/std/zig/parser.zig +++ b/std/zig/parser.zig @@ -3705,7 +3705,9 @@ pub const Parser = struct { }, ast.Node.Id.PrefixOp => { const prefix_op_node = @fieldParentPtr(ast.Node.PrefixOp, "base", base); - try stack.append(RenderState { .Expression = prefix_op_node.rhs }); + if (prefix_op_node.op != ast.Node.PrefixOp.Op.Deref) { + try stack.append(RenderState { .Expression = prefix_op_node.rhs }); + } switch (prefix_op_node.op) { ast.Node.PrefixOp.Op.AddrOf => |addr_of_info| { try stream.write("&"); @@ -3742,7 +3744,10 @@ pub const Parser = struct { }, ast.Node.PrefixOp.Op.BitNot => try stream.write("~"), ast.Node.PrefixOp.Op.BoolNot => try stream.write("!"), - ast.Node.PrefixOp.Op.Deref => try stream.write("*"), + ast.Node.PrefixOp.Op.Deref => { + try stack.append(RenderState { .Text = ".*" }); + try stack.append(RenderState { .Expression = prefix_op_node.rhs }); + }, ast.Node.PrefixOp.Op.Negation => try stream.write("-"), ast.Node.PrefixOp.Op.NegationWrap => try stream.write("-%"), ast.Node.PrefixOp.Op.Try => try stream.write("try "), diff --git a/test/cases/align.zig b/test/cases/align.zig index ad3a66a2e07d933e556268b308e48b12e8840929..a1259e96bf048c6cfadf109fc87b4128d9542677 100644 --- a/test/cases/align.zig +++ b/test/cases/align.zig @@ -10,7 +10,9 @@ test "global variable alignment" { assert(@typeOf(slice) == []align(4) u8); } -fn derp() align(@sizeOf(usize) * 2) i32 { return 1234; } +fn derp() align(@sizeOf(usize) * 2) i32 { + return 1234; +} fn noop1() align(1) void {} fn noop4() align(4) void {} @@ -22,7 +24,6 @@ test "function alignment" { noop4(); } - var baz: packed struct { a: u32, b: u32, @@ -32,7 +33,6 @@ test "packed struct alignment" { assert(@typeOf(&baz.b) == &align(1) u32); } - const blah: packed struct { a: u3, b: u3, @@ -53,29 +53,43 @@ test "implicitly decreasing pointer alignment" { assert(addUnaligned(&a, &b) == 7); } -fn addUnaligned(a: &align(1) const u32, b: &align(1) const u32) u32 { return *a + *b; } +fn addUnaligned(a: &align(1) const u32, b: &align(1) const u32) u32 { + return a.* + b.*; +} test "implicitly decreasing slice alignment" { const a: u32 align(4) = 3; const b: u32 align(8) = 4; assert(addUnalignedSlice((&a)[0..1], (&b)[0..1]) == 7); } -fn addUnalignedSlice(a: []align(1) const u32, b: []align(1) const u32) u32 { return a[0] + b[0]; } +fn addUnalignedSlice(a: []align(1) const u32, b: []align(1) const u32) u32 { + return a[0] + b[0]; +} test "specifying alignment allows pointer cast" { testBytesAlign(0x33); } fn testBytesAlign(b: u8) void { - var bytes align(4) = []u8{b, b, b, b}; + var bytes align(4) = []u8 { + b, + b, + b, + b, + }; const ptr = @ptrCast(&u32, &bytes[0]); - assert(*ptr == 0x33333333); + assert(ptr.* == 0x33333333); } test "specifying alignment allows slice cast" { testBytesAlignSlice(0x33); } fn testBytesAlignSlice(b: u8) void { - var bytes align(4) = []u8{b, b, b, b}; + var bytes align(4) = []u8 { + b, + b, + b, + b, + }; const slice = ([]u32)(bytes[0..]); assert(slice[0] == 0x33333333); } @@ -89,11 +103,14 @@ fn expectsOnly1(x: &align(1) u32) void { expects4(@alignCast(4, x)); } fn expects4(x: &align(4) u32) void { - *x += 1; + x.* += 1; } test "@alignCast slices" { - var array align(4) = []u32{1, 1}; + var array align(4) = []u32 { + 1, + 1, + }; const slice = array[0..]; sliceExpectsOnly1(slice); assert(slice[0] == 2); @@ -105,31 +122,34 @@ fn sliceExpects4(slice: []align(4) u32) void { slice[0] += 1; } - test "implicitly decreasing fn alignment" { testImplicitlyDecreaseFnAlign(alignedSmall, 1234); testImplicitlyDecreaseFnAlign(alignedBig, 5678); } -fn testImplicitlyDecreaseFnAlign(ptr: fn () align(1) i32, answer: i32) void { +fn testImplicitlyDecreaseFnAlign(ptr: fn() align(1) i32, answer: i32) void { assert(ptr() == answer); } -fn alignedSmall() align(8) i32 { return 1234; } -fn alignedBig() align(16) i32 { return 5678; } - +fn alignedSmall() align(8) i32 { + return 1234; +} +fn alignedBig() align(16) i32 { + return 5678; +} test "@alignCast functions" { assert(fnExpectsOnly1(simple4) == 0x19); } -fn fnExpectsOnly1(ptr: fn()align(1) i32) i32 { +fn fnExpectsOnly1(ptr: fn() align(1) i32) i32 { return fnExpects4(@alignCast(4, ptr)); } -fn fnExpects4(ptr: fn()align(4) i32) i32 { +fn fnExpects4(ptr: fn() align(4) i32) i32 { return ptr(); } -fn simple4() align(4) i32 { return 0x19; } - +fn simple4() align(4) i32 { + return 0x19; +} test "generic function with align param" { assert(whyWouldYouEverDoThis(1) == 0x1); @@ -137,8 +157,9 @@ test "generic function with align param" { assert(whyWouldYouEverDoThis(8) == 0x1); } -fn whyWouldYouEverDoThis(comptime align_bytes: u8) align(align_bytes) u8 { return 0x1; } - +fn whyWouldYouEverDoThis(comptime align_bytes: u8) align(align_bytes) u8 { + return 0x1; +} test "@ptrCast preserves alignment of bigger source" { var x: u32 align(16) = 1234; @@ -146,24 +167,38 @@ test "@ptrCast preserves alignment of bigger source" { assert(@typeOf(ptr) == &align(16) u8); } - test "compile-time known array index has best alignment possible" { // take full advantage of over-alignment - var array align(4) = []u8 {1, 2, 3, 4}; + var array align(4) = []u8 { + 1, + 2, + 3, + 4, + }; assert(@typeOf(&array[0]) == &align(4) u8); assert(@typeOf(&array[1]) == &u8); assert(@typeOf(&array[2]) == &align(2) u8); assert(@typeOf(&array[3]) == &u8); // because align is too small but we still figure out to use 2 - var bigger align(2) = []u64{1, 2, 3, 4}; + var bigger align(2) = []u64 { + 1, + 2, + 3, + 4, + }; assert(@typeOf(&bigger[0]) == &align(2) u64); assert(@typeOf(&bigger[1]) == &align(2) u64); assert(@typeOf(&bigger[2]) == &align(2) u64); assert(@typeOf(&bigger[3]) == &align(2) u64); // because pointer is align 2 and u32 align % 2 == 0 we can assume align 2 - var smaller align(2) = []u32{1, 2, 3, 4}; + var smaller align(2) = []u32 { + 1, + 2, + 3, + 4, + }; testIndex(&smaller[0], 0, &align(2) u32); testIndex(&smaller[0], 1, &align(2) u32); testIndex(&smaller[0], 2, &align(2) u32); @@ -182,7 +217,6 @@ fn testIndex2(ptr: &align(4) u8, index: usize, comptime T: type) void { assert(@typeOf(&ptr[index]) == T); } - test "alignstack" { assert(fnWithAlignedStack() == 1234); } diff --git a/test/cases/alignof.zig b/test/cases/alignof.zig index 27b95c7fdcbdc620b6a136702f5a6d849e4bd5ab..130a2a5b44d8e9e330114bf0608e288b1e66f9a8 100644 --- a/test/cases/alignof.zig +++ b/test/cases/alignof.zig @@ -1,7 +1,11 @@ const assert = @import("std").debug.assert; const builtin = @import("builtin"); -const Foo = struct { x: u32, y: u32, z: u32, }; +const Foo = struct { + x: u32, + y: u32, + z: u32, +}; test "@alignOf(T) before referencing T" { comptime assert(@alignOf(Foo) != @maxValue(usize)); diff --git a/test/cases/array.zig b/test/cases/array.zig index 577161dd16d8f9a2078adaef57fb45e955c98913..0fb61b2a9f4e6046085bbcdaadf4e3393c121eb9 100644 --- a/test/cases/array.zig +++ b/test/cases/array.zig @@ -2,9 +2,9 @@ const assert = @import("std").debug.assert; const mem = @import("std").mem; test "arrays" { - var array : [5]u32 = undefined; + var array: [5]u32 = undefined; - var i : u32 = 0; + var i: u32 = 0; while (i < 5) { array[i] = i + 1; i = array[i]; @@ -34,24 +34,41 @@ test "void arrays" { } test "array literal" { - const hex_mult = []u16{4096, 256, 16, 1}; + const hex_mult = []u16 { + 4096, + 256, + 16, + 1, + }; assert(hex_mult.len == 4); assert(hex_mult[1] == 256); } test "array dot len const expr" { - assert(comptime x: {break :x some_array.len == 4;}); + assert(comptime x: { + break :x some_array.len == 4; + }); } const ArrayDotLenConstExpr = struct { y: [some_array.len]u8, }; -const some_array = []u8 {0, 1, 2, 3}; - +const some_array = []u8 { + 0, + 1, + 2, + 3, +}; test "nested arrays" { - const array_of_strings = [][]const u8 {"hello", "this", "is", "my", "thing"}; + const array_of_strings = [][]const u8 { + "hello", + "this", + "is", + "my", + "thing", + }; for (array_of_strings) |s, i| { if (i == 0) assert(mem.eql(u8, s, "hello")); if (i == 1) assert(mem.eql(u8, s, "this")); @@ -61,7 +78,6 @@ test "nested arrays" { } } - var s_array: [8]Sub = undefined; const Sub = struct { b: u8, @@ -70,7 +86,9 @@ const Str = struct { a: []Sub, }; test "set global var array via slice embedded in struct" { - var s = Str { .a = s_array[0..]}; + var s = Str { + .a = s_array[0..], + }; s.a[0].b = 1; s.a[1].b = 2; @@ -82,7 +100,10 @@ test "set global var array via slice embedded in struct" { } test "array literal with specified size" { - var array = [2]u8{1, 2}; + var array = [2]u8 { + 1, + 2, + }; assert(array[0] == 1); assert(array[1] == 2); } diff --git a/test/cases/bitcast.zig b/test/cases/bitcast.zig index f1f2ccd6723ed7881912d32c33a54c4390cb6c2c..878140954a4ba1b216d0ec9297ddf172349ef218 100644 --- a/test/cases/bitcast.zig +++ b/test/cases/bitcast.zig @@ -10,5 +10,9 @@ fn testBitCast_i32_u32() void { assert(conv2(@maxValue(u32)) == -1); } -fn conv(x: i32) u32 { return @bitCast(u32, x); } -fn conv2(x: u32) i32 { return @bitCast(i32, x); } +fn conv(x: i32) u32 { + return @bitCast(u32, x); +} +fn conv2(x: u32) i32 { + return @bitCast(i32, x); +} diff --git a/test/cases/bugs/394.zig b/test/cases/bugs/394.zig index 071619d59ca6db979c44c795cd703febb3da4b11..a99bd18b2887a9744b590dfb47ef0d72d43b9d65 100644 --- a/test/cases/bugs/394.zig +++ b/test/cases/bugs/394.zig @@ -1,9 +1,20 @@ -const E = union(enum) { A: [9]u8, B: u64, }; -const S = struct { x: u8, y: E, }; +const E = union(enum) { + A: [9]u8, + B: u64, +}; +const S = struct { + x: u8, + y: E, +}; const assert = @import("std").debug.assert; test "bug 394 fixed" { - const x = S { .x = 3, .y = E {.B = 1 } }; + const x = S { + .x = 3, + .y = E { + .B = 1, + }, + }; assert(x.x == 3); } diff --git a/test/cases/bugs/655.zig b/test/cases/bugs/655.zig index e6a275004c5a1c7c7846bf0bea247b33afda32f3..4431767d5ca7f0884e1098a882e44c9b9283ea7e 100644 --- a/test/cases/bugs/655.zig +++ b/test/cases/bugs/655.zig @@ -8,5 +8,5 @@ test "function with &const parameter with type dereferenced by namespace" { } fn foo(x: &const other_file.Integer) void { - std.debug.assert(*x == 1234); + std.debug.assert(x.* == 1234); } diff --git a/test/cases/bugs/656.zig b/test/cases/bugs/656.zig index ce3eec8046724dc48cf26ac3048ab85f2e6d5004..24a28bf411bf92548250e6e88fc70dbcd0272ed5 100644 --- a/test/cases/bugs/656.zig +++ b/test/cases/bugs/656.zig @@ -14,12 +14,15 @@ test "nullable if after an if in a switch prong of a switch with 2 prongs in an } fn foo(a: bool, b: bool) void { - var prefix_op = PrefixOp { .AddrOf = Value { .align_expr = 1234 } }; - if (a) { - } else { + var prefix_op = PrefixOp { + .AddrOf = Value { + .align_expr = 1234, + }, + }; + if (a) {} else { switch (prefix_op) { PrefixOp.AddrOf => |addr_of_info| { - if (b) { } + if (b) {} if (addr_of_info.align_expr) |align_expr| { assert(align_expr == 1234); } diff --git a/test/cases/bugs/828.zig b/test/cases/bugs/828.zig index c46548cb7a5b46a471967eba79a3fd58e4de5cc6..8f329e4f82f4da2a9336cf50fe478544c807a547 100644 --- a/test/cases/bugs/828.zig +++ b/test/cases/bugs/828.zig @@ -1,10 +1,10 @@ const CountBy = struct { a: usize, - + const One = CountBy { .a = 1, }; - + pub fn counter(self: &const CountBy) Counter { return Counter { .i = 0, @@ -14,7 +14,7 @@ const CountBy = struct { const Counter = struct { i: usize, - + pub fn count(self: &Counter) bool { self.i += 1; return self.i <= 10; @@ -24,8 +24,8 @@ const Counter = struct { fn constCount(comptime cb: &const CountBy, comptime unused: u32) void { comptime { var cnt = cb.counter(); - if(cnt.i != 0) @compileError("Counter instance reused!"); - while(cnt.count()){} + if (cnt.i != 0) @compileError("Counter instance reused!"); + while (cnt.count()) {} } } diff --git a/test/cases/bugs/920.zig b/test/cases/bugs/920.zig index 13c03a304fe3c4254c1530b1f9bcea7def2ede38..c2b6816e94020b2740939d9f1c3d321a2cccf8b5 100644 --- a/test/cases/bugs/920.zig +++ b/test/cases/bugs/920.zig @@ -12,8 +12,7 @@ const ZigTable = struct { zero_case: fn(&Random, f64) f64, }; -fn ZigTableGen(comptime is_symmetric: bool, comptime r: f64, comptime v: f64, comptime f: fn(f64) f64, - comptime f_inv: fn(f64) f64, comptime zero_case: fn(&Random, f64) f64) ZigTable { +fn ZigTableGen(comptime is_symmetric: bool, comptime r: f64, comptime v: f64, comptime f: fn(f64) f64, comptime f_inv: fn(f64) f64, comptime zero_case: fn(&Random, f64) f64) ZigTable { var tables: ZigTable = undefined; tables.is_symmetric = is_symmetric; @@ -26,12 +25,12 @@ fn ZigTableGen(comptime is_symmetric: bool, comptime r: f64, comptime v: f64, co for (tables.x[2..256]) |*entry, i| { const last = tables.x[2 + i - 1]; - *entry = f_inv(v / last + f(last)); + entry.* = f_inv(v / last + f(last)); } tables.x[256] = 0; for (tables.f[0..]) |*entry, i| { - *entry = f(tables.x[i]); + entry.* = f(tables.x[i]); } return tables; @@ -40,9 +39,15 @@ fn ZigTableGen(comptime is_symmetric: bool, comptime r: f64, comptime v: f64, co const norm_r = 3.6541528853610088; const norm_v = 0.00492867323399; -fn norm_f(x: f64) f64 { return math.exp(-x * x / 2.0); } -fn norm_f_inv(y: f64) f64 { return math.sqrt(-2.0 * math.ln(y)); } -fn norm_zero_case(random: &Random, u: f64) f64 { return 0.0; } +fn norm_f(x: f64) f64 { + return math.exp(-x * x / 2.0); +} +fn norm_f_inv(y: f64) f64 { + return math.sqrt(-2.0 * math.ln(y)); +} +fn norm_zero_case(random: &Random, u: f64) f64 { + return 0.0; +} const NormalDist = blk: { @setEvalBranchQuota(30000); diff --git a/test/cases/cast.zig b/test/cases/cast.zig index 024ece0055c1e1952f3a29cdb8d67574a7f29dfe..547cca5797f3a5100b757cbbee91297355ffd080 100644 --- a/test/cases/cast.zig +++ b/test/cases/cast.zig @@ -14,10 +14,10 @@ test "integer literal to pointer cast" { } test "pointer reinterpret const float to int" { - const float: f64 = 5.99999999999994648725e-01; + const float: f64 = 5.99999999999994648725e - 01; const float_ptr = &float; const int_ptr = @ptrCast(&const i32, float_ptr); - const int_val = *int_ptr; + const int_val = int_ptr.*; assert(int_val == 858993411); } @@ -29,25 +29,31 @@ test "implicitly cast a pointer to a const pointer of it" { } fn funcWithConstPtrPtr(x: &const &i32) void { - **x += 1; + x.*.* += 1; } test "implicitly cast a container to a const pointer of it" { - const z = Struct(void) { .x = void{} }; + const z = Struct(void) { + .x = void{}, + }; assert(0 == @sizeOf(@typeOf(z))); assert(void{} == Struct(void).pointer(z).x); assert(void{} == Struct(void).pointer(&z).x); assert(void{} == Struct(void).maybePointer(z).x); assert(void{} == Struct(void).maybePointer(&z).x); assert(void{} == Struct(void).maybePointer(null).x); - const s = Struct(u8) { .x = 42 }; + const s = Struct(u8) { + .x = 42, + }; assert(0 != @sizeOf(@typeOf(s))); assert(42 == Struct(u8).pointer(s).x); assert(42 == Struct(u8).pointer(&s).x); assert(42 == Struct(u8).maybePointer(s).x); assert(42 == Struct(u8).maybePointer(&s).x); assert(0 == Struct(u8).maybePointer(null).x); - const u = Union { .x = 42 }; + const u = Union { + .x = 42, + }; assert(42 == Union.pointer(u).x); assert(42 == Union.pointer(&u).x); assert(42 == Union.maybePointer(u).x); @@ -67,12 +73,14 @@ fn Struct(comptime T: type) type { x: T, fn pointer(self: &const Self) Self { - return *self; + return self.*; } fn maybePointer(self: ?&const Self) Self { - const none = Self { .x = if (T == void) void{} else 0 }; - return *(self ?? &none); + const none = Self { + .x = if (T == void) void{} else 0, + }; + return (self ?? &none).*; } }; } @@ -81,12 +89,14 @@ const Union = union { x: u8, fn pointer(self: &const Union) Union { - return *self; + return self.*; } fn maybePointer(self: ?&const Union) Union { - const none = Union { .x = 0 }; - return *(self ?? &none); + const none = Union { + .x = 0, + }; + return (self ?? &none).*; } }; @@ -95,11 +105,11 @@ const Enum = enum { Some, fn pointer(self: &const Enum) Enum { - return *self; + return self.*; } fn maybePointer(self: ?&const Enum) Enum { - return *(self ?? &Enum.None); + return (self ?? &Enum.None).*; } }; @@ -108,19 +118,21 @@ test "implicitly cast indirect pointer to maybe-indirect pointer" { const Self = this; x: u8, fn constConst(p: &const &const Self) u8 { - return (*p).x; + return (p.*).x; } fn maybeConstConst(p: ?&const &const Self) u8 { - return (*??p).x; + return (??p.*).x; } fn constConstConst(p: &const &const &const Self) u8 { - return (**p).x; + return (p.*.*).x; } fn maybeConstConstConst(p: ?&const &const &const Self) u8 { - return (**??p).x; + return (??p.*.*).x; } }; - const s = S { .x = 42 }; + const s = S { + .x = 42, + }; const p = &s; const q = &p; const r = &q; @@ -154,7 +166,6 @@ fn boolToStr(b: bool) []const u8 { return if (b) "true" else "false"; } - test "peer resolve array and const slice" { testPeerResolveArrayConstSlice(true); comptime testPeerResolveArrayConstSlice(true); @@ -168,12 +179,12 @@ fn testPeerResolveArrayConstSlice(b: bool) void { test "integer literal to &const int" { const x: &const i32 = 3; - assert(*x == 3); + assert(x.* == 3); } test "string literal to &const []const u8" { const x: &const []const u8 = "hello"; - assert(mem.eql(u8, *x, "hello")); + assert(mem.eql(u8, x.*, "hello")); } test "implicitly cast from T to error!?T" { @@ -191,7 +202,9 @@ fn castToMaybeTypeError(z: i32) void { const f = z; const g: error!?i32 = f; - const a = A{ .a = z }; + const a = A { + .a = z, + }; const b: error!?A = a; assert((??(b catch unreachable)).a == 1); } @@ -205,7 +218,6 @@ fn implicitIntLitToMaybe() void { const g: error!?i32 = 1; } - test "return null from fn() error!?&T" { const a = returnNullFromMaybeTypeErrorRef(); const b = returnNullLitFromMaybeTypeErrorRef(); @@ -235,7 +247,6 @@ fn peerTypeTAndMaybeT(c: bool, b: bool) ?usize { return usize(3); } - test "peer type resolution: [0]u8 and []const u8" { assert(peerTypeEmptyArrayAndSlice(true, "hi").len == 0); assert(peerTypeEmptyArrayAndSlice(false, "hi").len == 1); @@ -246,7 +257,7 @@ test "peer type resolution: [0]u8 and []const u8" { } fn peerTypeEmptyArrayAndSlice(a: bool, slice: []const u8) []const u8 { if (a) { - return []const u8 {}; + return []const u8{}; } return slice[0..1]; @@ -261,7 +272,6 @@ fn castToMaybeSlice() ?[]const u8 { return "hi"; } - test "implicitly cast from [0]T to error![]T" { testCastZeroArrayToErrSliceMut(); comptime testCastZeroArrayToErrSliceMut(); @@ -329,7 +339,6 @@ fn foo(args: ...) void { assert(@typeOf(args[0]) == &const [5]u8); } - test "peer type resolution: error and [N]T" { // TODO: implicit error!T to error!U where T can implicitly cast to U //assert(mem.eql(u8, try testPeerErrorAndArray(0), "OK")); @@ -378,7 +387,12 @@ fn cast128Float(x: u128) f128 { } test "const slice widen cast" { - const bytes align(4) = []u8{0x12, 0x12, 0x12, 0x12}; + const bytes align(4) = []u8 { + 0x12, + 0x12, + 0x12, + 0x12, + }; const u32_value = ([]const u32)(bytes[0..])[0]; assert(u32_value == 0x12121212); diff --git a/test/cases/coroutines.zig b/test/cases/coroutines.zig index 46055d746985f7670e67bb08d0bd5b0513ce9c43..d00617eb7cb7a96460345e27795107803f549d8c 100644 --- a/test/cases/coroutines.zig +++ b/test/cases/coroutines.zig @@ -36,7 +36,7 @@ async fn testAsyncSeq() void { suspend; seq('d'); } -var points = []u8{0} ** "abcdefg".len; +var points = []u8 {0} ** "abcdefg".len; var index: usize = 0; fn seq(c: u8) void { @@ -94,7 +94,7 @@ async fn await_another() i32 { return 1234; } -var await_points = []u8{0} ** "abcdefghi".len; +var await_points = []u8 {0} ** "abcdefghi".len; var await_seq_index: usize = 0; fn await_seq(c: u8) void { @@ -102,7 +102,6 @@ fn await_seq(c: u8) void { await_seq_index += 1; } - var early_final_result: i32 = 0; test "coroutine await early return" { @@ -126,7 +125,7 @@ async fn early_another() i32 { return 1234; } -var early_points = []u8{0} ** "abcdef".len; +var early_points = []u8 {0} ** "abcdef".len; var early_seq_index: usize = 0; fn early_seq(c: u8) void { @@ -175,8 +174,8 @@ test "async fn pointer in a struct field" { } async<&std.mem.Allocator> fn simpleAsyncFn2(y: &i32) void { - defer *y += 2; - *y += 1; + defer y.* += 2; + y.* += 1; suspend; } @@ -205,7 +204,8 @@ test "error return trace across suspend points - async return" { cancel p2; } -fn nonFailing() promise->error!void { +// TODO https://github.com/zig-lang/zig/issues/760 +fn nonFailing() (promise->error!void) { return async suspendThenFail() catch unreachable; } @@ -238,7 +238,7 @@ async fn testBreakFromSuspend(my_result: &i32) void { s: suspend |p| { break :s; } - *my_result += 1; + my_result.* += 1; suspend; - *my_result += 1; + my_result.* += 1; } diff --git a/test/cases/defer.zig b/test/cases/defer.zig index 5470b4bbd09b3c8ca4be91836b641ebe8e8f215f..d2b00d1f911f8627cc6577097d1b3b3e997c954a 100644 --- a/test/cases/defer.zig +++ b/test/cases/defer.zig @@ -5,9 +5,18 @@ var index: usize = undefined; fn runSomeErrorDefers(x: bool) !bool { index = 0; - defer {result[index] = 'a'; index += 1;} - errdefer {result[index] = 'b'; index += 1;} - defer {result[index] = 'c'; index += 1;} + defer { + result[index] = 'a'; + index += 1; + } + errdefer { + result[index] = 'b'; + index += 1; + } + defer { + result[index] = 'c'; + index += 1; + } return if (x) x else error.FalseNotAllowed; } diff --git a/test/cases/enum.zig b/test/cases/enum.zig index 644c989b04812314adb35eb20e386dd60a1875d4..872e753f2057b7cb83c321de08aab808b53951ce 100644 --- a/test/cases/enum.zig +++ b/test/cases/enum.zig @@ -2,8 +2,15 @@ const assert = @import("std").debug.assert; const mem = @import("std").mem; test "enum type" { - const foo1 = Foo{ .One = 13}; - const foo2 = Foo{. Two = Point { .x = 1234, .y = 5678, }}; + const foo1 = Foo { + .One = 13, + }; + const foo2 = Foo { + .Two = Point { + .x = 1234, + .y = 5678, + }, + }; const bar = Bar.B; assert(bar == Bar.B); @@ -41,26 +48,31 @@ const Bar = enum { }; fn returnAnInt(x: i32) Foo { - return Foo { .One = x }; + return Foo { + .One = x, + }; } - test "constant enum with payload" { - var empty = AnEnumWithPayload {.Empty = {}}; - var full = AnEnumWithPayload {.Full = 13}; + var empty = AnEnumWithPayload { + .Empty = {}, + }; + var full = AnEnumWithPayload { + .Full = 13, + }; shouldBeEmpty(empty); shouldBeNotEmpty(full); } fn shouldBeEmpty(x: &const AnEnumWithPayload) void { - switch (*x) { + switch (x.*) { AnEnumWithPayload.Empty => {}, else => unreachable, } } fn shouldBeNotEmpty(x: &const AnEnumWithPayload) void { - switch (*x) { + switch (x.*) { AnEnumWithPayload.Empty => unreachable, else => {}, } @@ -71,8 +83,6 @@ const AnEnumWithPayload = union(enum) { Full: i32, }; - - const Number = enum { Zero, One, @@ -93,7 +103,6 @@ fn shouldEqual(n: Number, expected: u3) void { assert(u3(n) == expected); } - test "int to enum" { testIntToEnumEval(3); } @@ -108,7 +117,6 @@ const IntToEnumNumber = enum { Four, }; - test "@tagName" { assert(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three")); comptime assert(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three")); @@ -124,7 +132,6 @@ const BareNumber = enum { Three, }; - test "enum alignment" { comptime { assert(@alignOf(AlignTestEnum) >= @alignOf([9]u8)); @@ -137,47 +144,529 @@ const AlignTestEnum = union(enum) { B: u64, }; -const ValueCount1 = enum { I0 }; -const ValueCount2 = enum { I0, I1 }; +const ValueCount1 = enum { + I0, +}; +const ValueCount2 = enum { + I0, + I1, +}; const ValueCount256 = enum { - I0, I1, I2, I3, I4, I5, I6, I7, I8, I9, I10, I11, I12, I13, I14, I15, - I16, I17, I18, I19, I20, I21, I22, I23, I24, I25, I26, I27, I28, I29, I30, I31, - I32, I33, I34, I35, I36, I37, I38, I39, I40, I41, I42, I43, I44, I45, I46, I47, - I48, I49, I50, I51, I52, I53, I54, I55, I56, I57, I58, I59, I60, I61, I62, I63, - I64, I65, I66, I67, I68, I69, I70, I71, I72, I73, I74, I75, I76, I77, I78, I79, - I80, I81, I82, I83, I84, I85, I86, I87, I88, I89, I90, I91, I92, I93, I94, I95, - I96, I97, I98, I99, I100, I101, I102, I103, I104, I105, I106, I107, I108, I109, - I110, I111, I112, I113, I114, I115, I116, I117, I118, I119, I120, I121, I122, I123, - I124, I125, I126, I127, I128, I129, I130, I131, I132, I133, I134, I135, I136, I137, - I138, I139, I140, I141, I142, I143, I144, I145, I146, I147, I148, I149, I150, I151, - I152, I153, I154, I155, I156, I157, I158, I159, I160, I161, I162, I163, I164, I165, - I166, I167, I168, I169, I170, I171, I172, I173, I174, I175, I176, I177, I178, I179, - I180, I181, I182, I183, I184, I185, I186, I187, I188, I189, I190, I191, I192, I193, - I194, I195, I196, I197, I198, I199, I200, I201, I202, I203, I204, I205, I206, I207, - I208, I209, I210, I211, I212, I213, I214, I215, I216, I217, I218, I219, I220, I221, - I222, I223, I224, I225, I226, I227, I228, I229, I230, I231, I232, I233, I234, I235, - I236, I237, I238, I239, I240, I241, I242, I243, I244, I245, I246, I247, I248, I249, - I250, I251, I252, I253, I254, I255 + I0, + I1, + I2, + I3, + I4, + I5, + I6, + I7, + I8, + I9, + I10, + I11, + I12, + I13, + I14, + I15, + I16, + I17, + I18, + I19, + I20, + I21, + I22, + I23, + I24, + I25, + I26, + I27, + I28, + I29, + I30, + I31, + I32, + I33, + I34, + I35, + I36, + I37, + I38, + I39, + I40, + I41, + I42, + I43, + I44, + I45, + I46, + I47, + I48, + I49, + I50, + I51, + I52, + I53, + I54, + I55, + I56, + I57, + I58, + I59, + I60, + I61, + I62, + I63, + I64, + I65, + I66, + I67, + I68, + I69, + I70, + I71, + I72, + I73, + I74, + I75, + I76, + I77, + I78, + I79, + I80, + I81, + I82, + I83, + I84, + I85, + I86, + I87, + I88, + I89, + I90, + I91, + I92, + I93, + I94, + I95, + I96, + I97, + I98, + I99, + I100, + I101, + I102, + I103, + I104, + I105, + I106, + I107, + I108, + I109, + I110, + I111, + I112, + I113, + I114, + I115, + I116, + I117, + I118, + I119, + I120, + I121, + I122, + I123, + I124, + I125, + I126, + I127, + I128, + I129, + I130, + I131, + I132, + I133, + I134, + I135, + I136, + I137, + I138, + I139, + I140, + I141, + I142, + I143, + I144, + I145, + I146, + I147, + I148, + I149, + I150, + I151, + I152, + I153, + I154, + I155, + I156, + I157, + I158, + I159, + I160, + I161, + I162, + I163, + I164, + I165, + I166, + I167, + I168, + I169, + I170, + I171, + I172, + I173, + I174, + I175, + I176, + I177, + I178, + I179, + I180, + I181, + I182, + I183, + I184, + I185, + I186, + I187, + I188, + I189, + I190, + I191, + I192, + I193, + I194, + I195, + I196, + I197, + I198, + I199, + I200, + I201, + I202, + I203, + I204, + I205, + I206, + I207, + I208, + I209, + I210, + I211, + I212, + I213, + I214, + I215, + I216, + I217, + I218, + I219, + I220, + I221, + I222, + I223, + I224, + I225, + I226, + I227, + I228, + I229, + I230, + I231, + I232, + I233, + I234, + I235, + I236, + I237, + I238, + I239, + I240, + I241, + I242, + I243, + I244, + I245, + I246, + I247, + I248, + I249, + I250, + I251, + I252, + I253, + I254, + I255, }; const ValueCount257 = enum { - I0, I1, I2, I3, I4, I5, I6, I7, I8, I9, I10, I11, I12, I13, I14, I15, - I16, I17, I18, I19, I20, I21, I22, I23, I24, I25, I26, I27, I28, I29, I30, I31, - I32, I33, I34, I35, I36, I37, I38, I39, I40, I41, I42, I43, I44, I45, I46, I47, - I48, I49, I50, I51, I52, I53, I54, I55, I56, I57, I58, I59, I60, I61, I62, I63, - I64, I65, I66, I67, I68, I69, I70, I71, I72, I73, I74, I75, I76, I77, I78, I79, - I80, I81, I82, I83, I84, I85, I86, I87, I88, I89, I90, I91, I92, I93, I94, I95, - I96, I97, I98, I99, I100, I101, I102, I103, I104, I105, I106, I107, I108, I109, - I110, I111, I112, I113, I114, I115, I116, I117, I118, I119, I120, I121, I122, I123, - I124, I125, I126, I127, I128, I129, I130, I131, I132, I133, I134, I135, I136, I137, - I138, I139, I140, I141, I142, I143, I144, I145, I146, I147, I148, I149, I150, I151, - I152, I153, I154, I155, I156, I157, I158, I159, I160, I161, I162, I163, I164, I165, - I166, I167, I168, I169, I170, I171, I172, I173, I174, I175, I176, I177, I178, I179, - I180, I181, I182, I183, I184, I185, I186, I187, I188, I189, I190, I191, I192, I193, - I194, I195, I196, I197, I198, I199, I200, I201, I202, I203, I204, I205, I206, I207, - I208, I209, I210, I211, I212, I213, I214, I215, I216, I217, I218, I219, I220, I221, - I222, I223, I224, I225, I226, I227, I228, I229, I230, I231, I232, I233, I234, I235, - I236, I237, I238, I239, I240, I241, I242, I243, I244, I245, I246, I247, I248, I249, - I250, I251, I252, I253, I254, I255, I256 + I0, + I1, + I2, + I3, + I4, + I5, + I6, + I7, + I8, + I9, + I10, + I11, + I12, + I13, + I14, + I15, + I16, + I17, + I18, + I19, + I20, + I21, + I22, + I23, + I24, + I25, + I26, + I27, + I28, + I29, + I30, + I31, + I32, + I33, + I34, + I35, + I36, + I37, + I38, + I39, + I40, + I41, + I42, + I43, + I44, + I45, + I46, + I47, + I48, + I49, + I50, + I51, + I52, + I53, + I54, + I55, + I56, + I57, + I58, + I59, + I60, + I61, + I62, + I63, + I64, + I65, + I66, + I67, + I68, + I69, + I70, + I71, + I72, + I73, + I74, + I75, + I76, + I77, + I78, + I79, + I80, + I81, + I82, + I83, + I84, + I85, + I86, + I87, + I88, + I89, + I90, + I91, + I92, + I93, + I94, + I95, + I96, + I97, + I98, + I99, + I100, + I101, + I102, + I103, + I104, + I105, + I106, + I107, + I108, + I109, + I110, + I111, + I112, + I113, + I114, + I115, + I116, + I117, + I118, + I119, + I120, + I121, + I122, + I123, + I124, + I125, + I126, + I127, + I128, + I129, + I130, + I131, + I132, + I133, + I134, + I135, + I136, + I137, + I138, + I139, + I140, + I141, + I142, + I143, + I144, + I145, + I146, + I147, + I148, + I149, + I150, + I151, + I152, + I153, + I154, + I155, + I156, + I157, + I158, + I159, + I160, + I161, + I162, + I163, + I164, + I165, + I166, + I167, + I168, + I169, + I170, + I171, + I172, + I173, + I174, + I175, + I176, + I177, + I178, + I179, + I180, + I181, + I182, + I183, + I184, + I185, + I186, + I187, + I188, + I189, + I190, + I191, + I192, + I193, + I194, + I195, + I196, + I197, + I198, + I199, + I200, + I201, + I202, + I203, + I204, + I205, + I206, + I207, + I208, + I209, + I210, + I211, + I212, + I213, + I214, + I215, + I216, + I217, + I218, + I219, + I220, + I221, + I222, + I223, + I224, + I225, + I226, + I227, + I228, + I229, + I230, + I231, + I232, + I233, + I234, + I235, + I236, + I237, + I238, + I239, + I240, + I241, + I242, + I243, + I244, + I245, + I246, + I247, + I248, + I249, + I250, + I251, + I252, + I253, + I254, + I255, + I256, }; test "enum sizes" { @@ -189,11 +678,11 @@ test "enum sizes" { } } -const Small2 = enum (u2) { +const Small2 = enum(u2) { One, Two, }; -const Small = enum (u2) { +const Small = enum(u2) { One, Two, Three, @@ -213,8 +702,7 @@ test "set enum tag type" { } } - -const A = enum (u3) { +const A = enum(u3) { One, Two, Three, @@ -225,7 +713,7 @@ const A = enum (u3) { Four2, }; -const B = enum (u3) { +const B = enum(u3) { One3, Two3, Three3, @@ -236,7 +724,7 @@ const B = enum (u3) { Four23, }; -const C = enum (u2) { +const C = enum(u2) { One4, Two4, Three4, @@ -389,6 +877,8 @@ test "enum with tag values don't require parens" { } test "enum with 1 field but explicit tag type should still have the tag type" { - const Enum = enum(u8) { B = 2 }; + const Enum = enum(u8) { + B = 2, + }; comptime @import("std").debug.assert(@sizeOf(Enum) == @sizeOf(u8)); } diff --git a/test/cases/enum_with_members.zig b/test/cases/enum_with_members.zig index 0c2ae1c38385a37550aefff8aae71fb40d9e642a..9e3e031f922ade3464f9acae7e2b3123d1802fbf 100644 --- a/test/cases/enum_with_members.zig +++ b/test/cases/enum_with_members.zig @@ -7,7 +7,7 @@ const ET = union(enum) { UINT: u32, pub fn print(a: &const ET, buf: []u8) error!usize { - return switch (*a) { + return switch (a.*) { ET.SINT => |x| fmt.formatIntBuf(buf, x, 10, false, 0), ET.UINT => |x| fmt.formatIntBuf(buf, x, 10, false, 0), }; @@ -15,8 +15,12 @@ const ET = union(enum) { }; test "enum with members" { - const a = ET { .SINT = -42 }; - const b = ET { .UINT = 42 }; + const a = ET { + .SINT = -42, + }; + const b = ET { + .UINT = 42, + }; var buf: [20]u8 = undefined; assert((a.print(buf[0..]) catch unreachable) == 3); diff --git a/test/cases/error.zig b/test/cases/error.zig index 2a1433df5b715d0ca5e00d97cb82498c6a339caf..70d96e4d0196e659526075e5b447e959496e8fb0 100644 --- a/test/cases/error.zig +++ b/test/cases/error.zig @@ -30,14 +30,12 @@ test "@errorName" { assert(mem.eql(u8, @errorName(error.ALongerErrorName), "ALongerErrorName")); } - test "error values" { const a = i32(error.err1); const b = i32(error.err2); assert(a != b); } - test "redefinition of error values allowed" { shouldBeNotEqual(error.AnError, error.SecondError); } @@ -45,7 +43,6 @@ fn shouldBeNotEqual(a: error, b: error) void { if (a == b) unreachable; } - test "error binary operator" { const a = errBinaryOperatorG(true) catch 3; const b = errBinaryOperatorG(false) catch 3; @@ -56,20 +53,20 @@ fn errBinaryOperatorG(x: bool) error!isize { return if (x) error.ItBroke else isize(10); } - test "unwrap simple value from error" { const i = unwrapSimpleValueFromErrorDo() catch unreachable; assert(i == 13); } -fn unwrapSimpleValueFromErrorDo() error!isize { return 13; } - +fn unwrapSimpleValueFromErrorDo() error!isize { + return 13; +} test "error return in assignment" { doErrReturnInAssignment() catch unreachable; } fn doErrReturnInAssignment() error!void { - var x : i32 = undefined; + var x: i32 = undefined; x = try makeANonErr(); } @@ -95,7 +92,10 @@ test "error set type " { comptime testErrorSetType(); } -const MyErrSet = error {OutOfMemory, FileNotFound}; +const MyErrSet = error { + OutOfMemory, + FileNotFound, +}; fn testErrorSetType() void { assert(@memberCount(MyErrSet) == 2); @@ -109,14 +109,19 @@ fn testErrorSetType() void { } } - test "explicit error set cast" { testExplicitErrorSetCast(Set1.A); comptime testExplicitErrorSetCast(Set1.A); } -const Set1 = error{A, B}; -const Set2 = error{A, C}; +const Set1 = error { + A, + B, +}; +const Set2 = error { + A, + C, +}; fn testExplicitErrorSetCast(set1: Set1) void { var x = Set2(set1); @@ -129,7 +134,8 @@ test "comptime test error for empty error set" { comptime testComptimeTestErrorEmptySet(1234); } -const EmptyErrorSet = error {}; +const EmptyErrorSet = error { +}; fn testComptimeTestErrorEmptySet(x: EmptyErrorSet!i32) void { if (x) |v| assert(v == 1234) else |err| @compileError("bad"); @@ -145,7 +151,9 @@ test "comptime err to int of error set with only 1 possible value" { testErrToIntWithOnePossibleValue(error.A, u32(error.A)); comptime testErrToIntWithOnePossibleValue(error.A, u32(error.A)); } -fn testErrToIntWithOnePossibleValue(x: error{A}, comptime value: u32) void { +fn testErrToIntWithOnePossibleValue(x: error { + A, +}, comptime value: u32) void { if (u32(x) != value) { @compileError("bad"); } @@ -176,7 +184,6 @@ fn quux_1() !i32 { return error.C; } - test "error: fn returning empty error set can be passed as fn returning any error" { entry(); comptime entry(); @@ -186,24 +193,24 @@ fn entry() void { foo2(bar2); } -fn foo2(f: fn()error!void) void { +fn foo2(f: fn() error!void) void { const x = f(); } -fn bar2() (error{}!void) { } - +fn bar2() (error { +}!void) {} test "error: Zero sized error set returned with value payload crash" { _ = foo3(0); _ = comptime foo3(0); } -const Error = error{}; +const Error = error { +}; fn foo3(b: usize) Error!usize { return b; } - test "error: Infer error set from literals" { _ = nullLiteral("n") catch |err| handleErrors(err); _ = floatLiteral("n") catch |err| handleErrors(err); @@ -215,29 +222,26 @@ test "error: Infer error set from literals" { fn handleErrors(err: var) noreturn { switch (err) { - error.T => {} + error.T => {}, } unreachable; } fn nullLiteral(str: []const u8) !?i64 { - if (str[0] == 'n') - return null; + if (str[0] == 'n') return null; return error.T; } fn floatLiteral(str: []const u8) !?f64 { - if (str[0] == 'n') - return 1.0; + if (str[0] == 'n') return 1.0; return error.T; } fn intLiteral(str: []const u8) !?i64 { - if (str[0] == 'n') - return 1; + if (str[0] == 'n') return 1; return error.T; } diff --git a/test/cases/eval.zig b/test/cases/eval.zig index 364db5e152d6d64ad440c52369d26de48c92da91..2571686b0bcd92a4941edd51892f30320e032e66 100644 --- a/test/cases/eval.zig +++ b/test/cases/eval.zig @@ -11,8 +11,6 @@ fn fibonacci(x: i32) i32 { return fibonacci(x - 1) + fibonacci(x - 2); } - - fn unwrapAndAddOne(blah: ?i32) i32 { return ??blah + 1; } @@ -40,13 +38,13 @@ test "inline variable gets result of const if" { assert(gimme1or2(false) == 2); } - test "static function evaluation" { assert(statically_added_number == 3); } const statically_added_number = staticAdd(1, 2); -fn staticAdd(a: i32, b: i32) i32 { return a + b; } - +fn staticAdd(a: i32, b: i32) i32 { + return a + b; +} test "const expr eval on single expr blocks" { assert(constExprEvalOnSingleExprBlocksFn(1, true) == 3); @@ -64,9 +62,6 @@ fn constExprEvalOnSingleExprBlocksFn(x: i32, b: bool) i32 { return result; } - - - test "statically initialized list" { assert(static_point_list[0].x == 1); assert(static_point_list[0].y == 2); @@ -77,7 +72,10 @@ const Point = struct { x: i32, y: i32, }; -const static_point_list = []Point { makePoint(1, 2), makePoint(3, 4) }; +const static_point_list = []Point { + makePoint(1, 2), + makePoint(3, 4), +}; fn makePoint(x: i32, y: i32) Point { return Point { .x = x, @@ -85,7 +83,6 @@ fn makePoint(x: i32, y: i32) Point { }; } - test "static eval list init" { assert(static_vec3.data[2] == 1.0); assert(vec3(0.0, 0.0, 3.0).data[2] == 3.0); @@ -96,17 +93,19 @@ pub const Vec3 = struct { }; pub fn vec3(x: f32, y: f32, z: f32) Vec3 { return Vec3 { - .data = []f32 { x, y, z, }, + .data = []f32 { + x, + y, + z, + }, }; } - test "constant expressions" { - var array : [array_size]u8 = undefined; + var array: [array_size]u8 = undefined; assert(@sizeOf(@typeOf(array)) == 20); } -const array_size : u8 = 20; - +const array_size: u8 = 20; test "constant struct with negation" { assert(vertices[0].x == -0.6); @@ -119,12 +118,29 @@ const Vertex = struct { b: f32, }; const vertices = []Vertex { - Vertex { .x = -0.6, .y = -0.4, .r = 1.0, .g = 0.0, .b = 0.0 }, - Vertex { .x = 0.6, .y = -0.4, .r = 0.0, .g = 1.0, .b = 0.0 }, - Vertex { .x = 0.0, .y = 0.6, .r = 0.0, .g = 0.0, .b = 1.0 }, + Vertex { + .x = -0.6, + .y = -0.4, + .r = 1.0, + .g = 0.0, + .b = 0.0, + }, + Vertex { + .x = 0.6, + .y = -0.4, + .r = 0.0, + .g = 1.0, + .b = 0.0, + }, + Vertex { + .x = 0.0, + .y = 0.6, + .r = 0.0, + .g = 0.0, + .b = 1.0, + }, }; - test "statically initialized struct" { st_init_str_foo.x += 1; assert(st_init_str_foo.x == 14); @@ -133,15 +149,21 @@ const StInitStrFoo = struct { x: i32, y: bool, }; -var st_init_str_foo = StInitStrFoo { .x = 13, .y = true, }; - +var st_init_str_foo = StInitStrFoo { + .x = 13, + .y = true, +}; test "statically initalized array literal" { - const y : [4]u8 = st_init_arr_lit_x; + const y: [4]u8 = st_init_arr_lit_x; assert(y[3] == 4); } -const st_init_arr_lit_x = []u8{1,2,3,4}; - +const st_init_arr_lit_x = []u8 { + 1, + 2, + 3, + 4, +}; test "const slice" { comptime { @@ -198,14 +220,29 @@ const CmdFn = struct { func: fn(i32) i32, }; -const cmd_fns = []CmdFn{ - CmdFn {.name = "one", .func = one}, - CmdFn {.name = "two", .func = two}, - CmdFn {.name = "three", .func = three}, +const cmd_fns = []CmdFn { + CmdFn { + .name = "one", + .func = one, + }, + CmdFn { + .name = "two", + .func = two, + }, + CmdFn { + .name = "three", + .func = three, + }, }; -fn one(value: i32) i32 { return value + 1; } -fn two(value: i32) i32 { return value + 2; } -fn three(value: i32) i32 { return value + 3; } +fn one(value: i32) i32 { + return value + 1; +} +fn two(value: i32) i32 { + return value + 2; +} +fn three(value: i32) i32 { + return value + 3; +} fn performFn(comptime prefix_char: u8, start_value: i32) i32 { var result: i32 = start_value; @@ -229,7 +266,7 @@ test "eval @setRuntimeSafety at compile-time" { assert(result == 1234); } -fn fnWithSetRuntimeSafety() i32{ +fn fnWithSetRuntimeSafety() i32 { @setRuntimeSafety(true); return 1234; } @@ -244,7 +281,6 @@ fn fnWithFloatMode() f32 { return 1234.0; } - const SimpleStruct = struct { field: i32, @@ -253,7 +289,9 @@ const SimpleStruct = struct { } }; -var simple_struct = SimpleStruct{ .field = 1234, }; +var simple_struct = SimpleStruct { + .field = 1234, +}; const bound_fn = simple_struct.method; @@ -261,8 +299,6 @@ test "call method on bound fn referring to var instance" { assert(bound_fn() == 1237); } - - test "ptr to local array argument at comptime" { comptime { var bytes: [10]u8 = undefined; @@ -277,7 +313,6 @@ fn modifySomeBytes(bytes: []u8) void { bytes[9] = 'b'; } - test "comparisons 0 <= uint and 0 > uint should be comptime" { testCompTimeUIntComparisons(1234); } @@ -296,8 +331,6 @@ fn testCompTimeUIntComparisons(x: u32) void { } } - - test "const ptr to variable data changes at runtime" { assert(foo_ref.name[0] == 'a'); foo_ref.name = "b"; @@ -308,11 +341,11 @@ const Foo = struct { name: []const u8, }; -var foo_contents = Foo { .name = "a", }; +var foo_contents = Foo { + .name = "a", +}; const foo_ref = &foo_contents; - - test "create global array with for loop" { assert(global_array[5] == 5 * 5); assert(global_array[9] == 9 * 9); @@ -321,7 +354,7 @@ test "create global array with for loop" { const global_array = x: { var result: [10]usize = undefined; for (result) |*item, index| { - *item = index * index; + item.* = index * index; } break :x result; }; @@ -379,7 +412,7 @@ test "f128 at compile time is lossy" { pub fn TypeWithCompTimeSlice(comptime field_name: []const u8) type { return struct { - pub const Node = struct { }; + pub const Node = struct {}; }; } @@ -401,10 +434,10 @@ fn copyWithPartialInline(s: []u32, b: []u8) void { comptime var i: usize = 0; inline while (i < 4) : (i += 1) { s[i] = 0; - s[i] |= u32(b[i*4+0]) << 24; - s[i] |= u32(b[i*4+1]) << 16; - s[i] |= u32(b[i*4+2]) << 8; - s[i] |= u32(b[i*4+3]) << 0; + s[i] |= u32(b[i * 4 + 0]) << 24; + s[i] |= u32(b[i * 4 + 1]) << 16; + s[i] |= u32(b[i * 4 + 2]) << 8; + s[i] |= u32(b[i * 4 + 3]) << 0; } } @@ -413,7 +446,7 @@ test "binary math operator in partially inlined function" { var b: [16]u8 = undefined; for (b) |*r, i| - *r = u8(i + 1); + r.* = u8(i + 1); copyWithPartialInline(s[0..], b[0..]); assert(s[0] == 0x1020304); @@ -422,7 +455,6 @@ test "binary math operator in partially inlined function" { assert(s[3] == 0xd0e0f10); } - test "comptime function with the same args is memoized" { comptime { assert(MakeType(i32) == MakeType(i32)); @@ -447,12 +479,12 @@ test "comptime function with mutable pointer is not memoized" { } fn increment(value: &i32) void { - *value += 1; + value.* += 1; } fn generateTable(comptime T: type) [1010]T { - var res : [1010]T = undefined; - var i : usize = 0; + var res: [1010]T = undefined; + var i: usize = 0; while (i < 1010) : (i += 1) { res[i] = T(i); } @@ -496,9 +528,10 @@ const SingleFieldStruct = struct { } }; test "const ptr to comptime mutable data is not memoized" { - comptime { - var foo = SingleFieldStruct {.x = 1}; + var foo = SingleFieldStruct { + .x = 1, + }; assert(foo.read_x() == 1); foo.x = 2; assert(foo.read_x() == 2); diff --git a/test/cases/fn.zig b/test/cases/fn.zig index 5388deac104999287b267798f59635ffcb91f1ae..6d47dafad4ffae72b80ba18f3bd15acb0b54c72a 100644 --- a/test/cases/fn.zig +++ b/test/cases/fn.zig @@ -7,7 +7,6 @@ fn testParamsAdd(a: i32, b: i32) i32 { return a + b; } - test "local variables" { testLocVars(2); } @@ -16,7 +15,6 @@ fn testLocVars(b: i32) void { if (a + b != 3) unreachable; } - test "void parameters" { voidFun(1, void{}, 2, {}); } @@ -27,9 +25,8 @@ fn voidFun(a: i32, b: void, c: i32, d: void) void { return vv; } - test "mutable local variables" { - var zero : i32 = 0; + var zero: i32 = 0; assert(zero == 0); var i = i32(0); @@ -41,7 +38,7 @@ test "mutable local variables" { test "separate block scopes" { { - const no_conflict : i32 = 5; + const no_conflict: i32 = 5; assert(no_conflict == 5); } @@ -56,8 +53,7 @@ test "call function with empty string" { acceptsString(""); } -fn acceptsString(foo: []u8) void { } - +fn acceptsString(foo: []u8) void {} fn @"weird function name"() i32 { return 1234; @@ -70,31 +66,43 @@ test "implicit cast function unreachable return" { wantsFnWithVoid(fnWithUnreachable); } -fn wantsFnWithVoid(f: fn() void) void { } +fn wantsFnWithVoid(f: fn() void) void {} fn fnWithUnreachable() noreturn { unreachable; } - test "function pointers" { - const fns = []@typeOf(fn1) { fn1, fn2, fn3, fn4, }; + const fns = []@typeOf(fn1) { + fn1, + fn2, + fn3, + fn4, + }; for (fns) |f, i| { assert(f() == u32(i) + 5); } } -fn fn1() u32 {return 5;} -fn fn2() u32 {return 6;} -fn fn3() u32 {return 7;} -fn fn4() u32 {return 8;} - +fn fn1() u32 { + return 5; +} +fn fn2() u32 { + return 6; +} +fn fn3() u32 { + return 7; +} +fn fn4() u32 { + return 8; +} test "inline function call" { assert(@inlineCall(add, 3, 9) == 12); } -fn add(a: i32, b: i32) i32 { return a + b; } - +fn add(a: i32, b: i32) i32 { + return a + b; +} test "number literal as an argument" { numberLiteralArg(3); @@ -110,4 +118,4 @@ test "assign inline fn to const variable" { a(); } -inline fn inlineFn() void { } +inline fn inlineFn() void {} diff --git a/test/cases/for.zig b/test/cases/for.zig index 7bb0d7c9fa490f58fab652a0dece93e7b2baf418..f13e6ec6e5a0bfea4cecd41544f9b02825272348 100644 --- a/test/cases/for.zig +++ b/test/cases/for.zig @@ -3,8 +3,14 @@ const assert = std.debug.assert; const mem = std.mem; test "continue in for loop" { - const array = []i32 {1, 2, 3, 4, 5}; - var sum : i32 = 0; + const array = []i32 { + 1, + 2, + 3, + 4, + 5, + }; + var sum: i32 = 0; for (array) |x| { sum += x; if (x < 3) { @@ -24,17 +30,39 @@ test "for loop with pointer elem var" { } fn mangleString(s: []u8) void { for (s) |*c| { - *c += 1; + c.* += 1; } } test "basic for loop" { - const expected_result = []u8{9, 8, 7, 6, 0, 1, 2, 3, 9, 8, 7, 6, 0, 1, 2, 3 }; + const expected_result = []u8 { + 9, + 8, + 7, + 6, + 0, + 1, + 2, + 3, + 9, + 8, + 7, + 6, + 0, + 1, + 2, + 3, + }; var buffer: [expected_result.len]u8 = undefined; var buf_index: usize = 0; - const array = []u8 {9, 8, 7, 6}; + const array = []u8 { + 9, + 8, + 7, + 6, + }; for (array) |item| { buffer[buf_index] = item; buf_index += 1; @@ -65,7 +93,8 @@ fn testBreakOuter() void { var array = "aoeu"; var count: usize = 0; outer: for (array) |_| { - for (array) |_2| { // TODO shouldn't get error for redeclaring "_" + // TODO shouldn't get error for redeclaring "_" + for (array) |_2| { count += 1; break :outer; } @@ -82,7 +111,8 @@ fn testContinueOuter() void { var array = "aoeu"; var counter: usize = 0; outer: for (array) |_| { - for (array) |_2| { // TODO shouldn't get error for redeclaring "_" + // TODO shouldn't get error for redeclaring "_" + for (array) |_2| { counter += 1; continue :outer; } diff --git a/test/cases/generics.zig b/test/cases/generics.zig index 19b4a598d8706816b6b8f3475fae8f226c2b67b6..da8a7dcad6c230628c631af250677e8b3b17c76a 100644 --- a/test/cases/generics.zig +++ b/test/cases/generics.zig @@ -37,7 +37,6 @@ test "fn with comptime args" { assert(sameButWithFloats(0.43, 0.49) == 0.49); } - test "var params" { assert(max_i32(12, 34) == 34); assert(max_f64(1.2, 3.4) == 3.4); @@ -60,7 +59,6 @@ fn max_f64(a: f64, b: f64) f64 { return max_var(a, b); } - pub fn List(comptime T: type) type { return SmallList(T, 8); } @@ -82,10 +80,15 @@ test "function with return type type" { assert(list2.prealloc_items.len == 8); } - test "generic struct" { - var a1 = GenNode(i32) {.value = 13, .next = null,}; - var b1 = GenNode(bool) {.value = true, .next = null,}; + var a1 = GenNode(i32) { + .value = 13, + .next = null, + }; + var b1 = GenNode(bool) { + .value = true, + .next = null, + }; assert(a1.value == 13); assert(a1.value == a1.getVal()); assert(b1.getVal()); @@ -94,7 +97,9 @@ fn GenNode(comptime T: type) type { return struct { value: T, next: ?&GenNode(T), - fn getVal(n: &const GenNode(T)) T { return n.value; } + fn getVal(n: &const GenNode(T)) T { + return n.value; + } }; } @@ -107,7 +112,6 @@ fn GenericDataThing(comptime count: isize) type { }; } - test "use generic param in generic param" { assert(aGenericFn(i32, 3, 4) == 7); } @@ -115,21 +119,31 @@ fn aGenericFn(comptime T: type, comptime a: T, b: T) T { return a + b; } - test "generic fn with implicit cast" { assert(getFirstByte(u8, []u8 {13}) == 13); - assert(getFirstByte(u16, []u16 {0, 13}) == 0); + assert(getFirstByte(u16, []u16 { + 0, + 13, + }) == 0); +} +fn getByte(ptr: ?&const u8) u8 { + return ??ptr.*; } -fn getByte(ptr: ?&const u8) u8 {return *??ptr;} fn getFirstByte(comptime T: type, mem: []const T) u8 { return getByte(@ptrCast(&const u8, &mem[0])); } +const foos = []fn(var) bool { + foo1, + foo2, +}; -const foos = []fn(var) bool { foo1, foo2 }; - -fn foo1(arg: var) bool { return arg; } -fn foo2(arg: var) bool { return !arg; } +fn foo1(arg: var) bool { + return arg; +} +fn foo2(arg: var) bool { + return !arg; +} test "array of generic fns" { assert(foos[0](true)); diff --git a/test/cases/if.zig b/test/cases/if.zig index 2caae7448c5a6dc11ed1ac2ca778d4c85aa23ed5..808936bfa5fcf8dc01b1a5b326e3691ab59623a4 100644 --- a/test/cases/if.zig +++ b/test/cases/if.zig @@ -23,7 +23,6 @@ fn firstEqlThird(a: i32, b: i32, c: i32) void { } } - test "else if expression" { assert(elseIfExpressionF(1) == 1); } diff --git a/test/cases/import/a_namespace.zig b/test/cases/import/a_namespace.zig index 5cf906cf91ae238e36e7905243da960dd0f30e04..042f1867a5dd72fc0216b40f7f56962b7a8a8e9a 100644 --- a/test/cases/import/a_namespace.zig +++ b/test/cases/import/a_namespace.zig @@ -1 +1,3 @@ -pub fn foo() i32 { return 1234; } +pub fn foo() i32 { + return 1234; +} diff --git a/test/cases/ir_block_deps.zig b/test/cases/ir_block_deps.zig index 202df19f6285a21a144d2fe2fce3f06e456d7132..c017eca508e9f32e9137057decd6e9da89b0134a 100644 --- a/test/cases/ir_block_deps.zig +++ b/test/cases/ir_block_deps.zig @@ -11,7 +11,9 @@ fn foo(id: u64) !i32 { }; } -fn getErrInt() error!i32 { return 0; } +fn getErrInt() error!i32 { + return 0; +} test "ir block deps" { assert((foo(1) catch unreachable) == 0); diff --git a/test/cases/math.zig b/test/cases/math.zig index 47d001a590ef825053286615e57e8fe3ce41c332..dfc5946fdbd648c7a036474f305aa481fe867296 100644 --- a/test/cases/math.zig +++ b/test/cases/math.zig @@ -28,25 +28,12 @@ fn testDivision() void { assert(divTrunc(f32, -5.0, 3.0) == -1.0); comptime { - assert( - 1194735857077236777412821811143690633098347576 % - 508740759824825164163191790951174292733114988 == - 177254337427586449086438229241342047632117600); - assert(@rem(-1194735857077236777412821811143690633098347576, - 508740759824825164163191790951174292733114988) == - -177254337427586449086438229241342047632117600); - assert(1194735857077236777412821811143690633098347576 / - 508740759824825164163191790951174292733114988 == - 2); - assert(@divTrunc(-1194735857077236777412821811143690633098347576, - 508740759824825164163191790951174292733114988) == - -2); - assert(@divTrunc(1194735857077236777412821811143690633098347576, - -508740759824825164163191790951174292733114988) == - -2); - assert(@divTrunc(-1194735857077236777412821811143690633098347576, - -508740759824825164163191790951174292733114988) == - 2); + assert(1194735857077236777412821811143690633098347576 % 508740759824825164163191790951174292733114988 == 177254337427586449086438229241342047632117600); + assert(@rem(-1194735857077236777412821811143690633098347576, 508740759824825164163191790951174292733114988) == -177254337427586449086438229241342047632117600); + assert(1194735857077236777412821811143690633098347576 / 508740759824825164163191790951174292733114988 == 2); + assert(@divTrunc(-1194735857077236777412821811143690633098347576, 508740759824825164163191790951174292733114988) == -2); + assert(@divTrunc(1194735857077236777412821811143690633098347576, -508740759824825164163191790951174292733114988) == -2); + assert(@divTrunc(-1194735857077236777412821811143690633098347576, -508740759824825164163191790951174292733114988) == 2); assert(4126227191251978491697987544882340798050766755606969681711 % 10 == 1); } } @@ -114,18 +101,28 @@ fn ctz(x: var) usize { test "assignment operators" { var i: u32 = 0; - i += 5; assert(i == 5); - i -= 2; assert(i == 3); - i *= 20; assert(i == 60); - i /= 3; assert(i == 20); - i %= 11; assert(i == 9); - i <<= 1; assert(i == 18); - i >>= 2; assert(i == 4); + i += 5; + assert(i == 5); + i -= 2; + assert(i == 3); + i *= 20; + assert(i == 60); + i /= 3; + assert(i == 20); + i %= 11; + assert(i == 9); + i <<= 1; + assert(i == 18); + i >>= 2; + assert(i == 4); i = 6; - i &= 5; assert(i == 4); - i ^= 6; assert(i == 2); + i &= 5; + assert(i == 4); + i ^= 6; + assert(i == 2); i = 6; - i |= 3; assert(i == 7); + i |= 3; + assert(i == 7); } test "three expr in a row" { @@ -138,7 +135,7 @@ fn testThreeExprInARow(f: bool, t: bool) void { assertFalse(1 | 2 | 4 != 7); assertFalse(3 ^ 6 ^ 8 != 13); assertFalse(7 & 14 & 28 != 4); - assertFalse(9 << 1 << 2 != 9 << 3); + assertFalse(9 << 1 << 2 != 9 << 3); assertFalse(90 >> 1 >> 2 != 90 >> 3); assertFalse(100 - 1 + 1000 != 1099); assertFalse(5 * 4 / 2 % 3 != 1); @@ -150,7 +147,6 @@ fn assertFalse(b: bool) void { assert(!b); } - test "const number literal" { const one = 1; const eleven = ten + one; @@ -159,8 +155,6 @@ test "const number literal" { } const ten = 10; - - test "unsigned wrapping" { testUnsignedWrappingEval(@maxValue(u32)); comptime testUnsignedWrappingEval(@maxValue(u32)); @@ -214,8 +208,12 @@ const DivResult = struct { }; test "binary not" { - assert(comptime x: {break :x ~u16(0b1010101010101010) == 0b0101010101010101;}); - assert(comptime x: {break :x ~u64(2147483647) == 18446744071562067968;}); + assert(comptime x: { + break :x ~u16(0b1010101010101010) == 0b0101010101010101; + }); + assert(comptime x: { + break :x ~u64(2147483647) == 18446744071562067968; + }); testBinaryNot(0b1010101010101010); } @@ -319,27 +317,15 @@ fn testShrExact(x: u8) void { test "big number addition" { comptime { - assert( - 35361831660712422535336160538497375248 + - 101752735581729509668353361206450473702 == - 137114567242441932203689521744947848950); - assert( - 594491908217841670578297176641415611445982232488944558774612 + - 390603545391089362063884922208143568023166603618446395589768 == - 985095453608931032642182098849559179469148836107390954364380); + assert(35361831660712422535336160538497375248 + 101752735581729509668353361206450473702 == 137114567242441932203689521744947848950); + assert(594491908217841670578297176641415611445982232488944558774612 + 390603545391089362063884922208143568023166603618446395589768 == 985095453608931032642182098849559179469148836107390954364380); } } test "big number multiplication" { comptime { - assert( - 45960427431263824329884196484953148229 * - 128339149605334697009938835852565949723 == - 5898522172026096622534201617172456926982464453350084962781392314016180490567); - assert( - 594491908217841670578297176641415611445982232488944558774612 * - 390603545391089362063884922208143568023166603618446395589768 == - 232210647056203049913662402532976186578842425262306016094292237500303028346593132411865381225871291702600263463125370016); + assert(45960427431263824329884196484953148229 * 128339149605334697009938835852565949723 == 5898522172026096622534201617172456926982464453350084962781392314016180490567); + assert(594491908217841670578297176641415611445982232488944558774612 * 390603545391089362063884922208143568023166603618446395589768 == 232210647056203049913662402532976186578842425262306016094292237500303028346593132411865381225871291702600263463125370016); } } @@ -380,7 +366,9 @@ test "f128" { comptime test_f128(); } -fn make_f128(x: f128) f128 { return x; } +fn make_f128(x: f128) f128 { + return x; +} fn test_f128() void { assert(@sizeOf(f128) == 16); diff --git a/test/cases/misc.zig b/test/cases/misc.zig index 95a9a46bffc34018eaad450ed539a8b2c6f1e0fe..66487a49467959e58059663be1ad88ed1482d3d3 100644 --- a/test/cases/misc.zig +++ b/test/cases/misc.zig @@ -4,6 +4,7 @@ const cstr = @import("std").cstr; const builtin = @import("builtin"); // normal comment + /// this is a documentation comment /// doc comment line 2 fn emptyFunctionWithComments() void {} @@ -16,8 +17,7 @@ comptime { @export("disabledExternFn", disabledExternFn, builtin.GlobalLinkage.Internal); } -extern fn disabledExternFn() void { -} +extern fn disabledExternFn() void {} test "call disabled extern fn" { disabledExternFn(); @@ -110,17 +110,29 @@ fn testShortCircuit(f: bool, t: bool) void { var hit_3 = f; var hit_4 = f; - if (t or x: {assert(f); break :x f;}) { + if (t or x: { + assert(f); + break :x f; + }) { hit_1 = t; } - if (f or x: { hit_2 = t; break :x f; }) { + if (f or x: { + hit_2 = t; + break :x f; + }) { assert(f); } - if (t and x: { hit_3 = t; break :x f; }) { + if (t and x: { + hit_3 = t; + break :x f; + }) { assert(f); } - if (f and x: {assert(f); break :x f;}) { + if (f and x: { + assert(f); + break :x f; + }) { assert(f); } else { hit_4 = t; @@ -146,8 +158,8 @@ test "return string from function" { assert(mem.eql(u8, first4KeysOfHomeRow(), "aoeu")); } -const g1 : i32 = 1233 + 1; -var g2 : i32 = 0; +const g1: i32 = 1233 + 1; +var g2: i32 = 0; test "global variables" { assert(g2 == 0); @@ -155,10 +167,9 @@ test "global variables" { assert(g2 == 1234); } - test "memcpy and memset intrinsics" { - var foo : [20]u8 = undefined; - var bar : [20]u8 = undefined; + var foo: [20]u8 = undefined; + var bar: [20]u8 = undefined; @memset(&foo[0], 'A', foo.len); @memcpy(&bar[0], &foo[0], bar.len); @@ -167,12 +178,14 @@ test "memcpy and memset intrinsics" { } test "builtin static eval" { - const x : i32 = comptime x: {break :x 1 + 2 + 3;}; + const x: i32 = comptime x: { + break :x 1 + 2 + 3; + }; assert(x == comptime 6); } test "slicing" { - var array : [20]i32 = undefined; + var array: [20]i32 = undefined; array[5] = 1234; @@ -187,15 +200,15 @@ test "slicing" { if (slice_rest.len != 10) unreachable; } - test "constant equal function pointers" { const alias = emptyFn; - assert(comptime x: {break :x emptyFn == alias;}); + assert(comptime x: { + break :x emptyFn == alias; + }); } fn emptyFn() void {} - test "hex escape" { assert(mem.eql(u8, "\x68\x65\x6c\x6c\x6f", "hello")); } @@ -219,7 +232,7 @@ test "string escapes" { } test "multiline string" { - const s1 = + const s1 = \\one \\two) \\three @@ -229,7 +242,7 @@ test "multiline string" { } test "multiline C string" { - const s1 = + const s1 = c\\one c\\two) c\\three @@ -238,18 +251,16 @@ test "multiline C string" { assert(cstr.cmp(s1, s2) == 0); } - test "type equality" { assert(&const u8 != &u8); } - const global_a: i32 = 1234; const global_b: &const i32 = &global_a; const global_c: &const f32 = @ptrCast(&const f32, global_b); test "compile time global reinterpret" { const d = @ptrCast(&const i32, global_c); - assert(*d == 1234); + assert(d.* == 1234); } test "explicit cast maybe pointers" { @@ -261,12 +272,11 @@ test "generic malloc free" { const a = memAlloc(u8, 10) catch unreachable; memFree(u8, a); } -var some_mem : [100]u8 = undefined; +var some_mem: [100]u8 = undefined; fn memAlloc(comptime T: type, n: usize) error![]T { return @ptrCast(&T, &some_mem[0])[0..n]; } -fn memFree(comptime T: type, memory: []T) void { } - +fn memFree(comptime T: type, memory: []T) void {} test "cast undefined" { const array: [100]u8 = undefined; @@ -275,32 +285,35 @@ test "cast undefined" { } fn testCastUndefined(x: []const u8) void {} - test "cast small unsigned to larger signed" { assert(castSmallUnsignedToLargerSigned1(200) == i16(200)); assert(castSmallUnsignedToLargerSigned2(9999) == i64(9999)); } -fn castSmallUnsignedToLargerSigned1(x: u8) i16 { return x; } -fn castSmallUnsignedToLargerSigned2(x: u16) i64 { return x; } - +fn castSmallUnsignedToLargerSigned1(x: u8) i16 { + return x; +} +fn castSmallUnsignedToLargerSigned2(x: u16) i64 { + return x; +} test "implicit cast after unreachable" { assert(outer() == 1234); } -fn inner() i32 { return 1234; } +fn inner() i32 { + return 1234; +} fn outer() i64 { return inner(); } - test "pointer dereferencing" { var x = i32(3); const y = &x; - *y += 1; + y.* += 1; assert(x == 4); - assert(*y == 4); + assert(y.* == 4); } test "call result of if else expression" { @@ -310,9 +323,12 @@ test "call result of if else expression" { fn f2(x: bool) []const u8 { return (if (x) fA else fB)(); } -fn fA() []const u8 { return "a"; } -fn fB() []const u8 { return "b"; } - +fn fA() []const u8 { + return "a"; +} +fn fB() []const u8 { + return "b"; +} test "const expression eval handling of variables" { var x = true; @@ -321,8 +337,6 @@ test "const expression eval handling of variables" { } } - - test "constant enum initialization with differing sizes" { test3_1(test3_foo); test3_2(test3_bar); @@ -336,10 +350,17 @@ const Test3Point = struct { x: i32, y: i32, }; -const test3_foo = Test3Foo { .Three = Test3Point {.x = 3, .y = 4}}; -const test3_bar = Test3Foo { .Two = 13}; +const test3_foo = Test3Foo { + .Three = Test3Point { + .x = 3, + .y = 4, + }, +}; +const test3_bar = Test3Foo { + .Two = 13, +}; fn test3_1(f: &const Test3Foo) void { - switch (*f) { + switch (f.*) { Test3Foo.Three => |pt| { assert(pt.x == 3); assert(pt.y == 4); @@ -348,7 +369,7 @@ fn test3_1(f: &const Test3Foo) void { } } fn test3_2(f: &const Test3Foo) void { - switch (*f) { + switch (f.*) { Test3Foo.Two => |x| { assert(x == 13); }, @@ -356,23 +377,19 @@ fn test3_2(f: &const Test3Foo) void { } } - test "character literals" { assert('\'' == single_quote); } const single_quote = '\''; - - test "take address of parameter" { testTakeAddressOfParameter(12.34); } fn testTakeAddressOfParameter(f: f32) void { const f_ptr = &f; - assert(*f_ptr == 12.34); + assert(f_ptr.* == 12.34); } - test "pointer comparison" { const a = ([]const u8)("a"); const b = &a; @@ -382,23 +399,30 @@ fn ptrEql(a: &const []const u8, b: &const []const u8) bool { return a == b; } - test "C string concatenation" { const a = c"OK" ++ c" IT " ++ c"WORKED"; const b = c"OK IT WORKED"; const len = cstr.len(b); const len_with_null = len + 1; - {var i: u32 = 0; while (i < len_with_null) : (i += 1) { - assert(a[i] == b[i]); - }} + { + var i: u32 = 0; + while (i < len_with_null) : (i += 1) { + assert(a[i] == b[i]); + } + } assert(a[len] == 0); assert(b[len] == 0); } test "cast slice to u8 slice" { assert(@sizeOf(i32) == 4); - var big_thing_array = []i32{1, 2, 3, 4}; + var big_thing_array = []i32 { + 1, + 2, + 3, + 4, + }; const big_thing_slice: []i32 = big_thing_array[0..]; const bytes = ([]u8)(big_thing_slice); assert(bytes.len == 4 * 4); @@ -421,25 +445,22 @@ test "pointer to void return type" { } fn testPointerToVoidReturnType() error!void { const a = testPointerToVoidReturnType2(); - return *a; + return a.*; } const test_pointer_to_void_return_type_x = void{}; fn testPointerToVoidReturnType2() &const void { return &test_pointer_to_void_return_type_x; } - test "non const ptr to aliased type" { const int = i32; assert(?&int == ?&i32); } - - test "array 2D const double ptr" { const rect_2d_vertexes = [][1]f32 { - []f32{1.0}, - []f32{2.0}, + []f32 {1.0}, + []f32 {2.0}, }; testArray2DConstDoublePtr(&rect_2d_vertexes[0][0]); } @@ -450,10 +471,21 @@ fn testArray2DConstDoublePtr(ptr: &const f32) void { } const Tid = builtin.TypeId; -const AStruct = struct { x: i32, }; -const AnEnum = enum { One, Two, }; -const AUnionEnum = union(enum) { One: i32, Two: void, }; -const AUnion = union { One: void, Two: void }; +const AStruct = struct { + x: i32, +}; +const AnEnum = enum { + One, + Two, +}; +const AUnionEnum = union(enum) { + One: i32, + Two: void, +}; +const AUnion = union { + One: void, + Two: void, +}; test "@typeId" { comptime { @@ -481,9 +513,11 @@ test "@typeId" { assert(@typeId(@typeOf(AUnionEnum.One)) == Tid.Enum); assert(@typeId(AUnionEnum) == Tid.Union); assert(@typeId(AUnion) == Tid.Union); - assert(@typeId(fn()void) == Tid.Fn); + assert(@typeId(fn() void) == Tid.Fn); assert(@typeId(@typeOf(builtin)) == Tid.Namespace); - assert(@typeId(@typeOf(x: {break :x this;})) == Tid.Block); + assert(@typeId(@typeOf(x: { + break :x this; + })) == Tid.Block); // TODO bound fn // TODO arg tuple // TODO opaque @@ -499,8 +533,7 @@ test "@canImplicitCast" { } test "@typeName" { - const Struct = struct { - }; + const Struct = struct {}; const Union = union { unused: u8, }; @@ -525,14 +558,19 @@ fn TypeFromFn(comptime T: type) type { test "volatile load and store" { var number: i32 = 1234; const ptr = (&volatile i32)(&number); - *ptr += 1; - assert(*ptr == 1235); + ptr.* += 1; + assert(ptr.* == 1235); } test "slice string literal has type []const u8" { comptime { assert(@typeOf("aoeu"[0..]) == []const u8); - const array = []i32{1, 2, 3, 4}; + const array = []i32 { + 1, + 2, + 3, + 4, + }; assert(@typeOf(array[0..]) == []const i32); } } @@ -544,12 +582,15 @@ const GDTEntry = struct { field: i32, }; var gdt = []GDTEntry { - GDTEntry {.field = 1}, - GDTEntry {.field = 2}, + GDTEntry { + .field = 1, + }, + GDTEntry { + .field = 2, + }, }; var global_ptr = &gdt[0]; - // can't really run this test but we can make sure it has no compile error // and generates code const vram = @intToPtr(&volatile u8, 0x20000000)[0..0x8000]; @@ -584,7 +625,7 @@ test "comptime if inside runtime while which unconditionally breaks" { } fn testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(cond: bool) void { while (cond) { - if (false) { } + if (false) {} break; } } @@ -607,7 +648,9 @@ fn testStructInFn() void { kind: BlockKind, }; - var block = Block { .kind = 1234 }; + var block = Block { + .kind = 1234, + }; block.kind += 1; @@ -617,7 +660,9 @@ fn testStructInFn() void { fn fnThatClosesOverLocalConst() type { const c = 1; return struct { - fn g() i32 { return c; } + fn g() i32 { + return c; + } }; } @@ -635,22 +680,29 @@ fn thisIsAColdFn() void { @setCold(true); } - -const PackedStruct = packed struct { a: u8, b: u8, }; -const PackedUnion = packed union { a: u8, b: u32, }; -const PackedEnum = packed enum { A, B, }; +const PackedStruct = packed struct { + a: u8, + b: u8, +}; +const PackedUnion = packed union { + a: u8, + b: u32, +}; +const PackedEnum = packed enum { + A, + B, +}; test "packed struct, enum, union parameters in extern function" { - testPackedStuff( - PackedStruct{.a = 1, .b = 2}, - PackedUnion{.a = 1}, - PackedEnum.A, - ); -} - -export fn testPackedStuff(a: &const PackedStruct, b: &const PackedUnion, c: PackedEnum) void { + testPackedStuff(PackedStruct { + .a = 1, + .b = 2, + }, PackedUnion { + .a = 1, + }, PackedEnum.A); } +export fn testPackedStuff(a: &const PackedStruct, b: &const PackedUnion, c: PackedEnum) void {} test "slicing zero length array" { const s1 = ""[0..]; @@ -661,7 +713,6 @@ test "slicing zero length array" { assert(mem.eql(u32, s2, []u32{})); } - const addr1 = @ptrCast(&const u8, emptyFn); test "comptime cast fn to ptr" { const addr2 = @ptrCast(&const u8, emptyFn); diff --git a/test/cases/namespace_depends_on_compile_var/index.zig b/test/cases/namespace_depends_on_compile_var/index.zig index 95209dcef3d1b1c3395d000fa70af909b829b09e..ccc49d9367d83ba4c2e491e5539d7bcd31228cc6 100644 --- a/test/cases/namespace_depends_on_compile_var/index.zig +++ b/test/cases/namespace_depends_on_compile_var/index.zig @@ -8,7 +8,7 @@ test "namespace depends on compile var" { assert(!some_namespace.a_bool); } } -const some_namespace = switch(builtin.os) { +const some_namespace = switch (builtin.os) { builtin.Os.linux => @import("a.zig"), else => @import("b.zig"), }; diff --git a/test/cases/null.zig b/test/cases/null.zig index 35d72b729c22003745212e3603e6ad7bfc829f3a..96a62ab1edf1c84ebd8c4924ecba63121984ef99 100644 --- a/test/cases/null.zig +++ b/test/cases/null.zig @@ -1,7 +1,7 @@ const assert = @import("std").debug.assert; test "nullable type" { - const x : ?bool = true; + const x: ?bool = true; if (x) |y| { if (y) { @@ -13,13 +13,13 @@ test "nullable type" { unreachable; } - const next_x : ?i32 = null; + const next_x: ?i32 = null; const z = next_x ?? 1234; assert(z == 1234); - const final_x : ?i32 = 13; + const final_x: ?i32 = 13; const num = final_x ?? unreachable; @@ -30,19 +30,17 @@ test "test maybe object and get a pointer to the inner value" { var maybe_bool: ?bool = true; if (maybe_bool) |*b| { - *b = false; + b.* = false; } assert(??maybe_bool == false); } - test "rhs maybe unwrap return" { const x: ?bool = true; const y = x ?? return; } - test "maybe return" { maybeReturnImpl(); comptime maybeReturnImpl(); @@ -50,8 +48,7 @@ test "maybe return" { fn maybeReturnImpl() void { assert(??foo(1235)); - if (foo(null) != null) - unreachable; + if (foo(null) != null) unreachable; assert(!??foo(1234)); } @@ -60,12 +57,16 @@ fn foo(x: ?i32) ?bool { return value > 1234; } - test "if var maybe pointer" { - assert(shouldBeAPlus1(Particle {.a = 14, .b = 1, .c = 1, .d = 1}) == 15); + assert(shouldBeAPlus1(Particle { + .a = 14, + .b = 1, + .c = 1, + .d = 1, + }) == 15); } fn shouldBeAPlus1(p: &const Particle) u64 { - var maybe_particle: ?Particle = *p; + var maybe_particle: ?Particle = p.*; if (maybe_particle) |*particle| { particle.a += 1; } @@ -81,7 +82,6 @@ const Particle = struct { d: u64, }; - test "null literal outside function" { const is_null = here_is_a_null_literal.context == null; assert(is_null); @@ -96,7 +96,6 @@ const here_is_a_null_literal = SillyStruct { .context = null, }; - test "test null runtime" { testTestNullRuntime(null); } @@ -123,8 +122,6 @@ fn bar(x: ?void) ?void { } } - - const StructWithNullable = struct { field: ?i32, }; diff --git a/test/cases/ref_var_in_if_after_if_2nd_switch_prong.zig b/test/cases/ref_var_in_if_after_if_2nd_switch_prong.zig index 76cff3731aa25687bce1c0d63ff3b7c642665e77..3c94bb0d49bfa5c060eb6bafa152cf227f63eb7f 100644 --- a/test/cases/ref_var_in_if_after_if_2nd_switch_prong.zig +++ b/test/cases/ref_var_in_if_after_if_2nd_switch_prong.zig @@ -23,7 +23,7 @@ fn foo(c: bool, k: Num, c2: bool, b: []const u8) void { if (c) { const output_path = b; - if (c2) { } + if (c2) {} a(output_path); } diff --git a/test/cases/reflection.zig b/test/cases/reflection.zig index 0abc46c9de053d5c10ef964680f3f1fbfbbe914a..f9b64c80eb6f50bee40a1b27dc2e6fdacb83ef2e 100644 --- a/test/cases/reflection.zig +++ b/test/cases/reflection.zig @@ -23,7 +23,9 @@ test "reflection: function return type, var args, and param types" { } } -fn dummy(a: bool, b: i32, c: f32) i32 { return 1234; } +fn dummy(a: bool, b: i32, c: f32) i32 { + return 1234; +} fn dummy_varargs(args: ...) void {} test "reflection: struct member types and names" { @@ -54,7 +56,6 @@ test "reflection: enum member types and names" { assert(mem.eql(u8, @memberName(Bar, 2), "Three")); assert(mem.eql(u8, @memberName(Bar, 3), "Four")); } - } test "reflection: @field" { diff --git a/test/cases/slice.zig b/test/cases/slice.zig index ea708ba3b5f9823b53541f919c4e6151d43d7e13..4ca194672c113c793e7f6d7e64d143e1dba8b912 100644 --- a/test/cases/slice.zig +++ b/test/cases/slice.zig @@ -18,7 +18,11 @@ test "slice child property" { } test "runtime safety lets us slice from len..len" { - var an_array = []u8{1, 2, 3}; + var an_array = []u8 { + 1, + 2, + 3, + }; assert(mem.eql(u8, sliceFromLenToLen(an_array[0..], 3, 3), "")); } @@ -27,7 +31,7 @@ fn sliceFromLenToLen(a_slice: []u8, start: usize, end: usize) []u8 { } test "implicitly cast array of size 0 to slice" { - var msg = []u8 {}; + var msg = []u8{}; assertLenIsZero(msg); } diff --git a/test/cases/struct.zig b/test/cases/struct.zig index c3df97678b3ecdbc3bee29fc646a397fae41b5a8..c474d99f2bd2a718870c1752a5e67c9b49d34826 100644 --- a/test/cases/struct.zig +++ b/test/cases/struct.zig @@ -2,9 +2,11 @@ const assert = @import("std").debug.assert; const builtin = @import("builtin"); const StructWithNoFields = struct { - fn add(a: i32, b: i32) i32 { return a + b; } + fn add(a: i32, b: i32) i32 { + return a + b; + } }; -const empty_global_instance = StructWithNoFields {}; +const empty_global_instance = StructWithNoFields{}; test "call struct static method" { const result = StructWithNoFields.add(3, 4); @@ -34,12 +36,11 @@ test "void struct fields" { assert(@sizeOf(VoidStructFieldsFoo) == 4); } const VoidStructFieldsFoo = struct { - a : void, - b : i32, - c : void, + a: void, + b: i32, + c: void, }; - test "structs" { var foo: StructFoo = undefined; @memset(@ptrCast(&u8, &foo), 0, @sizeOf(StructFoo)); @@ -50,9 +51,9 @@ test "structs" { assert(foo.c == 100); } const StructFoo = struct { - a : i32, - b : bool, - c : f32, + a: i32, + b: bool, + c: f32, }; fn testFoo(foo: &const StructFoo) void { assert(foo.b); @@ -61,7 +62,6 @@ fn testMutation(foo: &StructFoo) void { foo.c = 100; } - const Node = struct { val: Val, next: &Node, @@ -72,10 +72,10 @@ const Val = struct { }; test "struct point to self" { - var root : Node = undefined; + var root: Node = undefined; root.val.x = 1; - var node : Node = undefined; + var node: Node = undefined; node.next = &root; node.val.x = 2; @@ -85,8 +85,8 @@ test "struct point to self" { } test "struct byval assign" { - var foo1 : StructFoo = undefined; - var foo2 : StructFoo = undefined; + var foo1: StructFoo = undefined; + var foo2: StructFoo = undefined; foo1.a = 1234; foo2.a = 0; @@ -96,46 +96,57 @@ test "struct byval assign" { } fn structInitializer() void { - const val = Val { .x = 42 }; + const val = Val { + .x = 42, + }; assert(val.x == 42); } - test "fn call of struct field" { - assert(callStructField(Foo {.ptr = aFunc,}) == 13); + assert(callStructField(Foo { + .ptr = aFunc, + }) == 13); } const Foo = struct { ptr: fn() i32, }; -fn aFunc() i32 { return 13; } +fn aFunc() i32 { + return 13; +} fn callStructField(foo: &const Foo) i32 { return foo.ptr(); } - test "store member function in variable" { - const instance = MemberFnTestFoo { .x = 1234, }; + const instance = MemberFnTestFoo { + .x = 1234, + }; const memberFn = MemberFnTestFoo.member; const result = memberFn(instance); assert(result == 1234); } const MemberFnTestFoo = struct { x: i32, - fn member(foo: &const MemberFnTestFoo) i32 { return foo.x; } + fn member(foo: &const MemberFnTestFoo) i32 { + return foo.x; + } }; - test "call member function directly" { - const instance = MemberFnTestFoo { .x = 1234, }; + const instance = MemberFnTestFoo { + .x = 1234, + }; const result = MemberFnTestFoo.member(instance); assert(result == 1234); } test "member functions" { - const r = MemberFnRand {.seed = 1234}; + const r = MemberFnRand { + .seed = 1234, + }; assert(r.getSeed() == 1234); } const MemberFnRand = struct { @@ -170,17 +181,16 @@ const EmptyStruct = struct { } }; - test "return empty struct from fn" { _ = testReturnEmptyStructFromFn(); } const EmptyStruct2 = struct {}; fn testReturnEmptyStructFromFn() EmptyStruct2 { - return EmptyStruct2 {}; + return EmptyStruct2{}; } test "pass slice of empty struct to fn" { - assert(testPassSliceOfEmptyStructToFn([]EmptyStruct2{ EmptyStruct2{} }) == 1); + assert(testPassSliceOfEmptyStructToFn([]EmptyStruct2 {EmptyStruct2{}}) == 1); } fn testPassSliceOfEmptyStructToFn(slice: []const EmptyStruct2) usize { return slice.len; @@ -201,7 +211,6 @@ test "packed struct" { assert(four == 4); } - const BitField1 = packed struct { a: u3, b: u3, @@ -301,7 +310,7 @@ test "packed array 24bits" { assert(@sizeOf(FooArray24Bits) == 2 + 2 * 3 + 2); } - var bytes = []u8{0} ** (@sizeOf(FooArray24Bits) + 1); + var bytes = []u8 {0} ** (@sizeOf(FooArray24Bits) + 1); bytes[bytes.len - 1] = 0xaa; const ptr = &([]FooArray24Bits)(bytes[0..bytes.len - 1])[0]; assert(ptr.a == 0); @@ -351,7 +360,7 @@ test "aligned array of packed struct" { assert(@sizeOf(FooArrayOfAligned) == 2 * 2); } - var bytes = []u8{0xbb} ** @sizeOf(FooArrayOfAligned); + var bytes = []u8 {0xbb} ** @sizeOf(FooArrayOfAligned); const ptr = &([]FooArrayOfAligned)(bytes[0..bytes.len])[0]; assert(ptr.a[0].a == 0xbb); @@ -360,11 +369,15 @@ test "aligned array of packed struct" { assert(ptr.a[1].b == 0xbb); } - - test "runtime struct initialization of bitfield" { - const s1 = Nibbles { .x = x1, .y = x1 }; - const s2 = Nibbles { .x = u4(x2), .y = u4(x2) }; + const s1 = Nibbles { + .x = x1, + .y = x1, + }; + const s2 = Nibbles { + .x = u4(x2), + .y = u4(x2), + }; assert(s1.x == x1); assert(s1.y == x1); @@ -394,7 +407,7 @@ test "native bit field understands endianness" { var all: u64 = 0x7765443322221111; var bytes: [8]u8 = undefined; @memcpy(&bytes[0], @ptrCast(&u8, &all), 8); - var bitfields = *@ptrCast(&Bitfields, &bytes[0]); + var bitfields = @ptrCast(&Bitfields, &bytes[0]).*; assert(bitfields.f1 == 0x1111); assert(bitfields.f2 == 0x2222); diff --git a/test/cases/struct_contains_null_ptr_itself.zig b/test/cases/struct_contains_null_ptr_itself.zig index 5864ef4038a45cea0e1d1e0e3c9eeb61e2981ab8..b6cb1a94cce3e4f274d683db1bb30efca2236d72 100644 --- a/test/cases/struct_contains_null_ptr_itself.zig +++ b/test/cases/struct_contains_null_ptr_itself.zig @@ -19,4 +19,3 @@ pub const Node = struct { pub const NodeLineComment = struct { base: Node, }; - diff --git a/test/cases/struct_contains_slice_of_itself.zig b/test/cases/struct_contains_slice_of_itself.zig index 45ec56c1e2cc3bebd645da34efc14f10c8934c1e..ee34c16baff39d91cf1ba4fbc1fe968f7231da49 100644 --- a/test/cases/struct_contains_slice_of_itself.zig +++ b/test/cases/struct_contains_slice_of_itself.zig @@ -6,7 +6,7 @@ const Node = struct { }; test "struct contains slice of itself" { - var other_nodes = []Node{ + var other_nodes = []Node { Node { .payload = 31, .children = []Node{}, diff --git a/test/cases/switch.zig b/test/cases/switch.zig index a0ac646160fede46715cb11b14fb79117b9ec656..b870297f18afdbc2cd7fe4219485b6266e45c4ea 100644 --- a/test/cases/switch.zig +++ b/test/cases/switch.zig @@ -6,7 +6,10 @@ test "switch with numbers" { fn testSwitchWithNumbers(x: u32) void { const result = switch (x) { - 1, 2, 3, 4 ... 8 => false, + 1, + 2, + 3, + 4 ... 8 => false, 13 => true, else => false, }; @@ -34,8 +37,10 @@ test "implicit comptime switch" { const result = switch (x) { 3 => 10, 4 => 11, - 5, 6 => 12, - 7, 8 => 13, + 5, + 6 => 12, + 7, + 8 => 13, else => 14, }; @@ -61,7 +66,6 @@ fn nonConstSwitchOnEnum(fruit: Fruit) void { } } - test "switch statement" { nonConstSwitch(SwitchStatmentFoo.C); } @@ -81,11 +85,16 @@ const SwitchStatmentFoo = enum { D, }; - test "switch prong with variable" { - switchProngWithVarFn(SwitchProngWithVarEnum { .One = 13}); - switchProngWithVarFn(SwitchProngWithVarEnum { .Two = 13.0}); - switchProngWithVarFn(SwitchProngWithVarEnum { .Meh = {}}); + switchProngWithVarFn(SwitchProngWithVarEnum { + .One = 13, + }); + switchProngWithVarFn(SwitchProngWithVarEnum { + .Two = 13.0, + }); + switchProngWithVarFn(SwitchProngWithVarEnum { + .Meh = {}, + }); } const SwitchProngWithVarEnum = union(enum) { One: i32, @@ -93,7 +102,7 @@ const SwitchProngWithVarEnum = union(enum) { Meh: void, }; fn switchProngWithVarFn(a: &const SwitchProngWithVarEnum) void { - switch(*a) { + switch (a.*) { SwitchProngWithVarEnum.One => |x| { assert(x == 13); }, @@ -112,9 +121,11 @@ test "switch on enum using pointer capture" { } fn testSwitchEnumPtrCapture() void { - var value = SwitchProngWithVarEnum { .One = 1234 }; + var value = SwitchProngWithVarEnum { + .One = 1234, + }; switch (value) { - SwitchProngWithVarEnum.One => |*x| *x += 1, + SwitchProngWithVarEnum.One => |*x| x.* += 1, else => unreachable, } switch (value) { @@ -125,8 +136,12 @@ fn testSwitchEnumPtrCapture() void { test "switch with multiple expressions" { const x = switch (returnsFive()) { - 1, 2, 3 => 1, - 4, 5, 6 => 2, + 1, + 2, + 3 => 1, + 4, + 5, + 6 => 2, else => i32(3), }; assert(x == 2); @@ -135,14 +150,15 @@ fn returnsFive() i32 { return 5; } - const Number = union(enum) { One: u64, Two: u8, Three: f32, }; -const number = Number { .Three = 1.23 }; +const number = Number { + .Three = 1.23, +}; fn returnsFalse() bool { switch (number) { @@ -198,7 +214,8 @@ fn testSwitchHandleAllCasesRange(x: u8) u8 { return switch (x) { 0 ... 100 => u8(0), 101 ... 200 => 1, - 201, 203 => 2, + 201, + 203 => 2, 202 => 4, 204 ... 255 => 3, }; diff --git a/test/cases/switch_prong_err_enum.zig b/test/cases/switch_prong_err_enum.zig index 136e8834e6eb38eaf67010ad3377a70109476ae7..2d28d2f4c7c27635c5b1ba3e13ac5246d3a65cf6 100644 --- a/test/cases/switch_prong_err_enum.zig +++ b/test/cases/switch_prong_err_enum.zig @@ -14,14 +14,18 @@ const FormValue = union(enum) { fn doThing(form_id: u64) error!FormValue { return switch (form_id) { - 17 => FormValue { .Address = try readOnce() }, + 17 => FormValue { + .Address = try readOnce(), + }, else => error.InvalidDebugInfo, }; } test "switch prong returns error enum" { switch (doThing(17) catch unreachable) { - FormValue.Address => |payload| { assert(payload == 1); }, + FormValue.Address => |payload| { + assert(payload == 1); + }, else => unreachable, } assert(read_count == 1); diff --git a/test/cases/switch_prong_implicit_cast.zig b/test/cases/switch_prong_implicit_cast.zig index 335feeef430ca5596d94a11c0065d0cd3fe37b6a..3d80f3fdb20e30b0817c093ae87228d985394102 100644 --- a/test/cases/switch_prong_implicit_cast.zig +++ b/test/cases/switch_prong_implicit_cast.zig @@ -7,8 +7,12 @@ const FormValue = union(enum) { fn foo(id: u64) !FormValue { return switch (id) { - 2 => FormValue { .Two = true }, - 1 => FormValue { .One = {} }, + 2 => FormValue { + .Two = true, + }, + 1 => FormValue { + .One = {}, + }, else => return error.Whatever, }; } diff --git a/test/cases/try.zig b/test/cases/try.zig index 4a0425e22e9644c7290ff9adf947f8a632f6428a..483bf6a91521a3ee7769bc054ad03ccc8e2b3a63 100644 --- a/test/cases/try.zig +++ b/test/cases/try.zig @@ -3,14 +3,12 @@ const assert = @import("std").debug.assert; test "try on error union" { tryOnErrorUnionImpl(); comptime tryOnErrorUnionImpl(); - } fn tryOnErrorUnionImpl() void { - const x = if (returnsTen()) |val| - val + 1 - else |err| switch (err) { - error.ItBroke, error.NoMem => 1, + const x = if (returnsTen()) |val| val + 1 else |err| switch (err) { + error.ItBroke, + error.NoMem => 1, error.CrappedOut => i32(2), else => unreachable, }; diff --git a/test/cases/undefined.zig b/test/cases/undefined.zig index bc81f9cf84bfdcdc77770a228d4ee124d4b78ca6..f1af10e532f12180906597f4d016a9684e2e00b1 100644 --- a/test/cases/undefined.zig +++ b/test/cases/undefined.zig @@ -63,6 +63,6 @@ test "assign undefined to struct with method" { } test "type name of undefined" { - const x = undefined; - assert(mem.eql(u8, @typeName(@typeOf(x)), "(undefined)")); + const x = undefined; + assert(mem.eql(u8, @typeName(@typeOf(x)), "(undefined)")); } diff --git a/test/cases/union.zig b/test/cases/union.zig index dc2a7c3414e4e521ab971d7cc05ed421ef7906ce..50cf8004b9aeb0733dbb6f12adf86a0b3b2c5354 100644 --- a/test/cases/union.zig +++ b/test/cases/union.zig @@ -10,38 +10,41 @@ const Agg = struct { val2: Value, }; -const v1 = Value { .Int = 1234 }; -const v2 = Value { .Array = []u8{3} ** 9 }; +const v1 = Value{ .Int = 1234 }; +const v2 = Value{ .Array = []u8{3} ** 9 }; -const err = (error!Agg)(Agg { +const err = (error!Agg)(Agg{ .val1 = v1, .val2 = v2, }); -const array = []Value { v1, v2, v1, v2}; - +const array = []Value{ + v1, + v2, + v1, + v2, +}; test "unions embedded in aggregate types" { switch (array[1]) { Value.Array => |arr| assert(arr[4] == 3), else => unreachable, } - switch((err catch unreachable).val1) { + switch ((err catch unreachable).val1) { Value.Int => |x| assert(x == 1234), else => unreachable, } } - const Foo = union { float: f64, int: i32, }; test "basic unions" { - var foo = Foo { .int = 1 }; + var foo = Foo{ .int = 1 }; assert(foo.int == 1); - foo = Foo {.float = 12.34}; + foo = Foo{ .float = 12.34 }; assert(foo.float == 12.34); } @@ -56,11 +59,11 @@ test "init union with runtime value" { } fn setFloat(foo: &Foo, x: f64) void { - *foo = Foo { .float = x }; + foo.* = Foo{ .float = x }; } fn setInt(foo: &Foo, x: i32) void { - *foo = Foo { .int = x }; + foo.* = Foo{ .int = x }; } const FooExtern = extern union { @@ -69,13 +72,12 @@ const FooExtern = extern union { }; test "basic extern unions" { - var foo = FooExtern { .int = 1 }; + var foo = FooExtern{ .int = 1 }; assert(foo.int == 1); foo.float = 12.34; assert(foo.float == 12.34); } - const Letter = enum { A, B, @@ -93,12 +95,12 @@ test "union with specified enum tag" { } fn doTest() void { - assert(bar(Payload {.A = 1234}) == -10); + assert(bar(Payload{ .A = 1234 }) == -10); } fn bar(value: &const Payload) i32 { - assert(Letter(*value) == Letter.A); - return switch (*value) { + assert(Letter(value.*) == Letter.A); + return switch (value.*) { Payload.A => |x| return x - 1244, Payload.B => |x| if (x == 12.34) i32(20) else 21, Payload.C => |x| if (x) i32(30) else 31, @@ -131,13 +133,13 @@ const MultipleChoice2 = union(enum(u32)) { test "union(enum(u32)) with specified and unspecified tag values" { comptime assert(@TagType(@TagType(MultipleChoice2)) == u32); - testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2 {.C = 123}); - comptime testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2 { .C = 123} ); + testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2{ .C = 123 }); + comptime testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2{ .C = 123 }); } fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: &const MultipleChoice2) void { - assert(u32(@TagType(MultipleChoice2)(*x)) == 60); - assert(1123 == switch (*x) { + assert(u32(@TagType(MultipleChoice2)(x.*)) == 60); + assert(1123 == switch (x.*) { MultipleChoice2.A => 1, MultipleChoice2.B => 2, MultipleChoice2.C => |v| i32(1000) + v, @@ -150,10 +152,9 @@ fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: &const MultipleChoice2) void }); } - const ExternPtrOrInt = extern union { ptr: &u8, - int: u64 + int: u64, }; test "extern union size" { comptime assert(@sizeOf(ExternPtrOrInt) == 8); @@ -161,7 +162,7 @@ test "extern union size" { const PackedPtrOrInt = packed union { ptr: &u8, - int: u64 + int: u64, }; test "extern union size" { comptime assert(@sizeOf(PackedPtrOrInt) == 8); @@ -174,8 +175,16 @@ test "union with only 1 field which is void should be zero bits" { comptime assert(@sizeOf(ZeroBits) == 0); } -const TheTag = enum {A, B, C}; -const TheUnion = union(TheTag) { A: i32, B: i32, C: i32 }; +const TheTag = enum { + A, + B, + C, +}; +const TheUnion = union(TheTag) { + A: i32, + B: i32, + C: i32, +}; test "union field access gives the enum values" { assert(TheUnion.A == TheTag.A); assert(TheUnion.B == TheTag.B); @@ -183,20 +192,28 @@ test "union field access gives the enum values" { } test "cast union to tag type of union" { - testCastUnionToTagType(TheUnion {.B = 1234}); - comptime testCastUnionToTagType(TheUnion {.B = 1234}); + testCastUnionToTagType(TheUnion{ .B = 1234 }); + comptime testCastUnionToTagType(TheUnion{ .B = 1234 }); } fn testCastUnionToTagType(x: &const TheUnion) void { - assert(TheTag(*x) == TheTag.B); + assert(TheTag(x.*) == TheTag.B); } test "cast tag type of union to union" { var x: Value2 = Letter2.B; assert(Letter2(x) == Letter2.B); } -const Letter2 = enum { A, B, C }; -const Value2 = union(Letter2) { A: i32, B, C, }; +const Letter2 = enum { + A, + B, + C, +}; +const Value2 = union(Letter2) { + A: i32, + B, + C, +}; test "implicit cast union to its tag type" { var x: Value2 = Letter2.B; @@ -217,19 +234,16 @@ const TheUnion2 = union(enum) { }; fn assertIsTheUnion2Item1(value: &const TheUnion2) void { - assert(*value == TheUnion2.Item1); + assert(value.* == TheUnion2.Item1); } - pub const PackThis = union(enum) { Invalid: bool, StringLiteral: u2, }; test "constant packed union" { - testConstPackedUnion([]PackThis { - PackThis { .StringLiteral = 1 }, - }); + testConstPackedUnion([]PackThis{PackThis{ .StringLiteral = 1 }}); } fn testConstPackedUnion(expected_tokens: []const PackThis) void { @@ -242,7 +256,7 @@ test "switch on union with only 1 field" { switch (r) { PartialInst.Compiled => { var z: PartialInstWithPayload = undefined; - z = PartialInstWithPayload { .Compiled = 1234 }; + z = PartialInstWithPayload{ .Compiled = 1234 }; switch (z) { PartialInstWithPayload.Compiled => |x| { assert(x == 1234); @@ -261,4 +275,3 @@ const PartialInst = union(enum) { const PartialInstWithPayload = union(enum) { Compiled: i32, }; - diff --git a/test/cases/var_args.zig b/test/cases/var_args.zig index cead9eb8bf6c483f2bc372cca44db191a5985925..81f800568c57ec9cd2a0997dcc7bdd3fdf1648d7 100644 --- a/test/cases/var_args.zig +++ b/test/cases/var_args.zig @@ -2,9 +2,12 @@ const assert = @import("std").debug.assert; fn add(args: ...) i32 { var sum = i32(0); - {comptime var i: usize = 0; inline while (i < args.len) : (i += 1) { - sum += args[i]; - }} + { + comptime var i: usize = 0; + inline while (i < args.len) : (i += 1) { + sum += args[i]; + } + } return sum; } @@ -55,18 +58,23 @@ fn extraFn(extra: u32, args: ...) usize { return args.len; } +const foos = []fn(...) bool { + foo1, + foo2, +}; -const foos = []fn(...) bool { foo1, foo2 }; - -fn foo1(args: ...) bool { return true; } -fn foo2(args: ...) bool { return false; } +fn foo1(args: ...) bool { + return true; +} +fn foo2(args: ...) bool { + return false; +} test "array of var args functions" { assert(foos[0]()); assert(!foos[1]()); } - test "pass array and slice of same array to var args should have same pointers" { const array = "hi"; const slice: []const u8 = array; @@ -79,7 +87,6 @@ fn assertSlicePtrsEql(args: ...) void { assert(s1.ptr == s2.ptr); } - test "pass zero length array to var args param" { doNothingWithFirstArg(""); } diff --git a/test/cases/while.zig b/test/cases/while.zig index 33d5a5623acfd9a5c4c2d49942f3cccdf748f32f..574a7b7e761ca2606b7fce715b30112293905f44 100644 --- a/test/cases/while.zig +++ b/test/cases/while.zig @@ -1,7 +1,7 @@ const assert = @import("std").debug.assert; test "while loop" { - var i : i32 = 0; + var i: i32 = 0; while (i < 4) { i += 1; } @@ -35,7 +35,7 @@ test "continue and break" { } var continue_and_break_counter: i32 = 0; fn runContinueAndBreakTest() void { - var i : i32 = 0; + var i: i32 = 0; while (true) { continue_and_break_counter += 2; i += 1; @@ -58,10 +58,13 @@ fn returnWithImplicitCastFromWhileLoopTest() error!void { test "while with continue expression" { var sum: i32 = 0; - {var i: i32 = 0; while (i < 10) : (i += 1) { - if (i == 5) continue; - sum += i; - }} + { + var i: i32 = 0; + while (i < 10) : (i += 1) { + if (i == 5) continue; + sum += i; + } + } assert(sum == 40); } @@ -117,17 +120,13 @@ test "while with error union condition" { var numbers_left: i32 = undefined; fn getNumberOrErr() error!i32 { - return if (numbers_left == 0) - error.OutOfNumbers - else x: { + return if (numbers_left == 0) error.OutOfNumbers else x: { numbers_left -= 1; break :x numbers_left; }; } fn getNumberOrNull() ?i32 { - return if (numbers_left == 0) - null - else x: { + return if (numbers_left == 0) null else x: { numbers_left -= 1; break :x numbers_left; }; @@ -136,42 +135,48 @@ fn getNumberOrNull() ?i32 { test "while on nullable with else result follow else prong" { const result = while (returnNull()) |value| { break value; - } else i32(2); + } else + i32(2); assert(result == 2); } test "while on nullable with else result follow break prong" { const result = while (returnMaybe(10)) |value| { break value; - } else i32(2); + } else + i32(2); assert(result == 10); } test "while on error union with else result follow else prong" { const result = while (returnError()) |value| { break value; - } else |err| i32(2); + } else|err| + i32(2); assert(result == 2); } test "while on error union with else result follow break prong" { const result = while (returnSuccess(10)) |value| { break value; - } else |err| i32(2); + } else|err| + i32(2); assert(result == 10); } test "while on bool with else result follow else prong" { const result = while (returnFalse()) { break i32(10); - } else i32(2); + } else + i32(2); assert(result == 2); } test "while on bool with else result follow break prong" { const result = while (returnTrue()) { break i32(10); - } else i32(2); + } else + i32(2); assert(result == 10); } @@ -202,9 +207,21 @@ fn testContinueOuter() void { } } -fn returnNull() ?i32 { return null; } -fn returnMaybe(x: i32) ?i32 { return x; } -fn returnError() error!i32 { return error.YouWantedAnError; } -fn returnSuccess(x: i32) error!i32 { return x; } -fn returnFalse() bool { return false; } -fn returnTrue() bool { return true; } +fn returnNull() ?i32 { + return null; +} +fn returnMaybe(x: i32) ?i32 { + return x; +} +fn returnError() error!i32 { + return error.YouWantedAnError; +} +fn returnSuccess(x: i32) error!i32 { + return x; +} +fn returnFalse() bool { + return false; +} +fn returnTrue() bool { + return true; +} -- 2.54.0 From ac4d55dec1e32ddef945bfa246eb78f20f31ec44 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 1 May 2018 01:53:04 -0400 Subject: [PATCH 03/47] behavior tests passing with new pointer deref syntax --- std/array_list.zig | 54 +- std/fmt/index.zig | 93 ++- std/heap.zig | 106 ++-- std/io.zig | 65 +- std/linked_list.zig | 95 +-- std/os/index.zig | 80 ++- std/os/linux/index.zig | 371 ++++++----- std/special/bootstrap.zig | 8 +- std/special/compiler_rt/fixuint.zig | 6 +- std/special/compiler_rt/fixunsdfdi.zig | 1 - std/special/compiler_rt/fixunsdfsi.zig | 1 - std/special/compiler_rt/fixunssfti.zig | 1 - std/special/compiler_rt/fixunstfti.zig | 1 - std/special/compiler_rt/index.zig | 818 ++++++++++++++++++++----- std/special/compiler_rt/udivmod.zig | 43 +- std/special/compiler_rt/udivmodti4.zig | 2 +- std/special/compiler_rt/umodti3.zig | 2 +- test/cases/cast.zig | 6 +- test/cases/generics.zig | 2 +- 19 files changed, 1128 insertions(+), 627 deletions(-) diff --git a/std/array_list.zig b/std/array_list.zig index 2a44b66518ebfce906d3e55a94fc381e27e0d93e..8c8426e1e5a901ed506f6f9b2f4e3c75e1736d01 100644 --- a/std/array_list.zig +++ b/std/array_list.zig @@ -8,7 +8,7 @@ pub fn ArrayList(comptime T: type) type { return AlignedArrayList(T, @alignOf(T)); } -pub fn AlignedArrayList(comptime T: type, comptime A: u29) type{ +pub fn AlignedArrayList(comptime T: type, comptime A: u29) type { return struct { const Self = this; @@ -21,7 +21,7 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) type{ /// Deinitialize with `deinit` or use `toOwnedSlice`. pub fn init(allocator: &Allocator) Self { - return Self { + return Self{ .items = []align(A) T{}, .len = 0, .allocator = allocator, @@ -48,7 +48,7 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) type{ /// allocated with `allocator`. /// Deinitialize with `deinit` or use `toOwnedSlice`. pub fn fromOwnedSlice(allocator: &Allocator, slice: []align(A) T) Self { - return Self { + return Self{ .items = slice, .len = slice.len, .allocator = allocator, @@ -59,7 +59,7 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) type{ pub fn toOwnedSlice(self: &Self) []align(A) T { const allocator = self.allocator; const result = allocator.alignedShrink(T, A, self.items, self.len); - *self = init(allocator); + self.* = init(allocator); return result; } @@ -67,21 +67,21 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) type{ try l.ensureCapacity(l.len + 1); l.len += 1; - mem.copy(T, l.items[n+1..l.len], l.items[n..l.len-1]); - l.items[n] = *item; + mem.copy(T, l.items[n + 1..l.len], l.items[n..l.len - 1]); + l.items[n] = item.*; } pub fn insertSlice(l: &Self, n: usize, items: []align(A) const T) !void { try l.ensureCapacity(l.len + items.len); l.len += items.len; - mem.copy(T, l.items[n+items.len..l.len], l.items[n..l.len-items.len]); - mem.copy(T, l.items[n..n+items.len], items); + mem.copy(T, l.items[n + items.len..l.len], l.items[n..l.len - items.len]); + mem.copy(T, l.items[n..n + items.len], items); } pub fn append(l: &Self, item: &const T) !void { const new_item_ptr = try l.addOne(); - *new_item_ptr = *item; + new_item_ptr.* = item.*; } pub fn appendSlice(l: &Self, items: []align(A) const T) !void { @@ -124,8 +124,7 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) type{ } pub fn popOrNull(self: &Self) ?T { - if (self.len == 0) - return null; + if (self.len == 0) return null; return self.pop(); } }; @@ -135,25 +134,35 @@ test "basic ArrayList test" { var list = ArrayList(i32).init(debug.global_allocator); defer list.deinit(); - {var i: usize = 0; while (i < 10) : (i += 1) { - list.append(i32(i + 1)) catch unreachable; - }} + { + var i: usize = 0; + while (i < 10) : (i += 1) { + list.append(i32(i + 1)) catch unreachable; + } + } - {var i: usize = 0; while (i < 10) : (i += 1) { - assert(list.items[i] == i32(i + 1)); - }} + { + var i: usize = 0; + while (i < 10) : (i += 1) { + assert(list.items[i] == i32(i + 1)); + } + } assert(list.pop() == 10); assert(list.len == 9); - list.appendSlice([]const i32 { 1, 2, 3 }) catch unreachable; + list.appendSlice([]const i32{ + 1, + 2, + 3, + }) catch unreachable; assert(list.len == 12); assert(list.pop() == 3); assert(list.pop() == 2); assert(list.pop() == 1); assert(list.len == 9); - list.appendSlice([]const i32 {}) catch unreachable; + list.appendSlice([]const i32{}) catch unreachable; assert(list.len == 9); } @@ -166,12 +175,15 @@ test "insert ArrayList test" { assert(list.items[0] == 5); assert(list.items[1] == 1); - try list.insertSlice(1, []const i32 { 9, 8 }); + try list.insertSlice(1, []const i32{ + 9, + 8, + }); assert(list.items[0] == 5); assert(list.items[1] == 9); assert(list.items[2] == 8); - const items = []const i32 { 1 }; + const items = []const i32{1}; try list.insertSlice(0, items[0..0]); assert(list.items[0] == 5); } diff --git a/std/fmt/index.zig b/std/fmt/index.zig index 43e758038f397f76c2b21b0cc8cc8dace754253e..804fd802f1872e69ec80c99a9596399e5804a899 100644 --- a/std/fmt/index.zig +++ b/std/fmt/index.zig @@ -11,9 +11,7 @@ const max_int_digits = 65; /// Renders fmt string with args, calling output with slices of bytes. /// If `output` returns an error, the error is returned from `format` and /// `output` is not called again. -pub fn format(context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8) Errors!void, - comptime fmt: []const u8, args: ...) Errors!void -{ +pub fn format(context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8) Errors!void, comptime fmt: []const u8, args: ...) Errors!void { const State = enum { Start, OpenBrace, @@ -221,7 +219,7 @@ pub fn format(context: var, comptime Errors: type, output: fn(@typeOf(context), } } -pub fn formatValue(value: var, context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8)Errors!void) Errors!void { +pub fn formatValue(value: var, context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8) Errors!void) Errors!void { const T = @typeOf(value); switch (@typeId(T)) { builtin.TypeId.Int => { @@ -256,7 +254,7 @@ pub fn formatValue(value: var, context: var, comptime Errors: type, output: fn(@ }, builtin.TypeId.Pointer => { if (@typeId(T.Child) == builtin.TypeId.Array and T.Child.Child == u8) { - return output(context, (*value)[0..]); + return output(context, (value.*)[0..]); } else { return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(value)); } @@ -270,13 +268,11 @@ pub fn formatValue(value: var, context: var, comptime Errors: type, output: fn(@ } } -pub fn formatAsciiChar(c: u8, context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8)Errors!void) Errors!void { +pub fn formatAsciiChar(c: u8, context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8) Errors!void) Errors!void { return output(context, (&c)[0..1]); } -pub fn formatBuf(buf: []const u8, width: usize, - context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8)Errors!void) Errors!void -{ +pub fn formatBuf(buf: []const u8, width: usize, context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8) Errors!void) Errors!void { try output(context, buf); var leftover_padding = if (width > buf.len) (width - buf.len) else return; @@ -289,7 +285,7 @@ pub fn formatBuf(buf: []const u8, width: usize, // Print a float in scientific notation to the specified precision. Null uses full precision. // It should be the case that every full precision, printed value can be re-parsed back to the // same type unambiguously. -pub fn formatFloatScientific(value: var, maybe_precision: ?usize, context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8)Errors!void) Errors!void { +pub fn formatFloatScientific(value: var, maybe_precision: ?usize, context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8) Errors!void) Errors!void { var x = f64(value); // Errol doesn't handle these special cases. @@ -338,7 +334,7 @@ pub fn formatFloatScientific(value: var, maybe_precision: ?usize, context: var, var printed: usize = 0; if (float_decimal.digits.len > 1) { const num_digits = math.min(float_decimal.digits.len, precision + 1); - try output(context, float_decimal.digits[1 .. num_digits]); + try output(context, float_decimal.digits[1..num_digits]); printed += num_digits - 1; } @@ -350,12 +346,9 @@ pub fn formatFloatScientific(value: var, maybe_precision: ?usize, context: var, try output(context, float_decimal.digits[0..1]); try output(context, "."); if (float_decimal.digits.len > 1) { - const num_digits = if (@typeOf(value) == f32) - math.min(usize(9), float_decimal.digits.len) - else - float_decimal.digits.len; + const num_digits = if (@typeOf(value) == f32) math.min(usize(9), float_decimal.digits.len) else float_decimal.digits.len; - try output(context, float_decimal.digits[1 .. num_digits]); + try output(context, float_decimal.digits[1..num_digits]); } else { try output(context, "0"); } @@ -381,7 +374,7 @@ pub fn formatFloatScientific(value: var, maybe_precision: ?usize, context: var, // Print a float of the format x.yyyyy where the number of y is specified by the precision argument. // By default floats are printed at full precision (no rounding). -pub fn formatFloatDecimal(value: var, maybe_precision: ?usize, context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8)Errors!void) Errors!void { +pub fn formatFloatDecimal(value: var, maybe_precision: ?usize, context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8) Errors!void) Errors!void { var x = f64(value); // Errol doesn't handle these special cases. @@ -431,14 +424,14 @@ pub fn formatFloatDecimal(value: var, maybe_precision: ?usize, context: var, com if (num_digits_whole > 0) { // We may have to zero pad, for instance 1e4 requires zero padding. - try output(context, float_decimal.digits[0 .. num_digits_whole_no_pad]); + try output(context, float_decimal.digits[0..num_digits_whole_no_pad]); var i = num_digits_whole_no_pad; while (i < num_digits_whole) : (i += 1) { try output(context, "0"); } } else { - try output(context , "0"); + try output(context, "0"); } // {.0} special case doesn't want a trailing '.' @@ -470,10 +463,10 @@ pub fn formatFloatDecimal(value: var, maybe_precision: ?usize, context: var, com // Remaining fractional portion, zero-padding if insufficient. debug.assert(precision >= printed); if (num_digits_whole_no_pad + precision - printed < float_decimal.digits.len) { - try output(context, float_decimal.digits[num_digits_whole_no_pad .. num_digits_whole_no_pad + precision - printed]); + try output(context, float_decimal.digits[num_digits_whole_no_pad..num_digits_whole_no_pad + precision - printed]); return; } else { - try output(context, float_decimal.digits[num_digits_whole_no_pad ..]); + try output(context, float_decimal.digits[num_digits_whole_no_pad..]); printed += float_decimal.digits.len - num_digits_whole_no_pad; while (printed < precision) : (printed += 1) { @@ -489,14 +482,14 @@ pub fn formatFloatDecimal(value: var, maybe_precision: ?usize, context: var, com if (num_digits_whole > 0) { // We may have to zero pad, for instance 1e4 requires zero padding. - try output(context, float_decimal.digits[0 .. num_digits_whole_no_pad]); + try output(context, float_decimal.digits[0..num_digits_whole_no_pad]); var i = num_digits_whole_no_pad; while (i < num_digits_whole) : (i += 1) { try output(context, "0"); } } else { - try output(context , "0"); + try output(context, "0"); } // Omit `.` if no fractional portion @@ -516,14 +509,11 @@ pub fn formatFloatDecimal(value: var, maybe_precision: ?usize, context: var, com } } - try output(context, float_decimal.digits[num_digits_whole_no_pad ..]); + try output(context, float_decimal.digits[num_digits_whole_no_pad..]); } } - -pub fn formatInt(value: var, base: u8, uppercase: bool, width: usize, - context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8)Errors!void) Errors!void -{ +pub fn formatInt(value: var, base: u8, uppercase: bool, width: usize, context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8) Errors!void) Errors!void { if (@typeOf(value).is_signed) { return formatIntSigned(value, base, uppercase, width, context, Errors, output); } else { @@ -531,9 +521,7 @@ pub fn formatInt(value: var, base: u8, uppercase: bool, width: usize, } } -fn formatIntSigned(value: var, base: u8, uppercase: bool, width: usize, - context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8)Errors!void) Errors!void -{ +fn formatIntSigned(value: var, base: u8, uppercase: bool, width: usize, context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8) Errors!void) Errors!void { const uint = @IntType(false, @typeOf(value).bit_count); if (value < 0) { const minus_sign: u8 = '-'; @@ -552,9 +540,7 @@ fn formatIntSigned(value: var, base: u8, uppercase: bool, width: usize, } } -fn formatIntUnsigned(value: var, base: u8, uppercase: bool, width: usize, - context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8)Errors!void) Errors!void -{ +fn formatIntUnsigned(value: var, base: u8, uppercase: bool, width: usize, context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8) Errors!void) Errors!void { // max_int_digits accounts for the minus sign. when printing an unsigned // number we don't need to do that. var buf: [max_int_digits - 1]u8 = undefined; @@ -566,8 +552,7 @@ fn formatIntUnsigned(value: var, base: u8, uppercase: bool, width: usize, index -= 1; buf[index] = digitToChar(u8(digit), uppercase); a /= base; - if (a == 0) - break; + if (a == 0) break; } const digits_buf = buf[index..]; @@ -579,8 +564,7 @@ fn formatIntUnsigned(value: var, base: u8, uppercase: bool, width: usize, while (true) { try output(context, (&zero_byte)[0..1]); leftover_padding -= 1; - if (leftover_padding == 0) - break; + if (leftover_padding == 0) break; } mem.set(u8, buf[0..index], '0'); return output(context, buf); @@ -592,7 +576,7 @@ fn formatIntUnsigned(value: var, base: u8, uppercase: bool, width: usize, } pub fn formatIntBuf(out_buf: []u8, value: var, base: u8, uppercase: bool, width: usize) usize { - var context = FormatIntBuf { + var context = FormatIntBuf{ .out_buf = out_buf, .index = 0, }; @@ -609,10 +593,8 @@ fn formatIntCallback(context: &FormatIntBuf, bytes: []const u8) (error{}!void) { } pub fn parseInt(comptime T: type, buf: []const u8, radix: u8) !T { - if (!T.is_signed) - return parseUnsigned(T, buf, radix); - if (buf.len == 0) - return T(0); + if (!T.is_signed) return parseUnsigned(T, buf, radix); + if (buf.len == 0) return T(0); if (buf[0] == '-') { return math.negate(try parseUnsigned(T, buf[1..], radix)); } else if (buf[0] == '+') { @@ -632,9 +614,10 @@ test "fmt.parseInt" { assert(if (parseInt(u8, "256", 10)) |_| false else |err| err == error.Overflow); } -const ParseUnsignedError = error { +const ParseUnsignedError = error{ /// The result cannot fit in the type specified Overflow, + /// The input had a byte that was not a digit InvalidCharacter, }; @@ -659,8 +642,7 @@ pub fn charToDigit(c: u8, radix: u8) (error{InvalidCharacter}!u8) { else => return error.InvalidCharacter, }; - if (value >= radix) - return error.InvalidCharacter; + if (value >= radix) return error.InvalidCharacter; return value; } @@ -684,20 +666,21 @@ fn bufPrintWrite(context: &BufPrintContext, bytes: []const u8) !void { } pub fn bufPrint(buf: []u8, comptime fmt: []const u8, args: ...) ![]u8 { - var context = BufPrintContext { .remaining = buf, }; + var context = BufPrintContext{ .remaining = buf }; try format(&context, error{BufferTooSmall}, bufPrintWrite, fmt, args); return buf[0..buf.len - context.remaining.len]; } pub fn allocPrint(allocator: &mem.Allocator, comptime fmt: []const u8, args: ...) ![]u8 { var size: usize = 0; - format(&size, error{}, countSize, fmt, args) catch |err| switch (err) {}; + format(&size, error{}, countSize, fmt, args) catch |err| switch (err) { + }; const buf = try allocator.alloc(u8, size); return bufPrint(buf, fmt, args); } fn countSize(size: &usize, bytes: []const u8) (error{}!void) { - *size += bytes.len; + size.* += bytes.len; } test "buf print int" { @@ -773,9 +756,7 @@ test "fmt.format" { unused: u8, }; var buf1: [32]u8 = undefined; - const value = Struct { - .unused = 42, - }; + const value = Struct{ .unused = 42 }; const result = try bufPrint(buf1[0..], "pointer: {}\n", &value); assert(mem.startsWith(u8, result, "pointer: Struct@")); } @@ -988,7 +969,7 @@ test "fmt.format" { pub fn trim(buf: []const u8) []const u8 { var start: usize = 0; - while (start < buf.len and isWhiteSpace(buf[start])) : (start += 1) { } + while (start < buf.len and isWhiteSpace(buf[start])) : (start += 1) {} var end: usize = buf.len; while (true) { @@ -1000,7 +981,6 @@ pub fn trim(buf: []const u8) []const u8 { } } break; - } return buf[start..end]; } @@ -1015,7 +995,10 @@ test "fmt.trim" { pub fn isWhiteSpace(byte: u8) bool { return switch (byte) { - ' ', '\t', '\n', '\r' => true, + ' ', + '\t', + '\n', + '\r' => true, else => false, }; } diff --git a/std/heap.zig b/std/heap.zig index bfdf62f658a2cac52a9c730747ef05119c247f5f..7b753524a6ca5760fd78a1b85a716c914501efac 100644 --- a/std/heap.zig +++ b/std/heap.zig @@ -10,7 +10,7 @@ const c = std.c; const Allocator = mem.Allocator; pub const c_allocator = &c_allocator_state; -var c_allocator_state = Allocator { +var c_allocator_state = Allocator{ .allocFn = cAlloc, .reallocFn = cRealloc, .freeFn = cFree, @@ -18,10 +18,7 @@ var c_allocator_state = Allocator { fn cAlloc(self: &Allocator, n: usize, alignment: u29) ![]u8 { assert(alignment <= @alignOf(c_longdouble)); - return if (c.malloc(n)) |buf| - @ptrCast(&u8, buf)[0..n] - else - error.OutOfMemory; + return if (c.malloc(n)) |buf| @ptrCast(&u8, buf)[0..n] else error.OutOfMemory; } fn cRealloc(self: &Allocator, old_mem: []u8, new_size: usize, alignment: u29) ![]u8 { @@ -48,8 +45,8 @@ pub const DirectAllocator = struct { const HeapHandle = if (builtin.os == Os.windows) os.windows.HANDLE else void; pub fn init() DirectAllocator { - return DirectAllocator { - .allocator = Allocator { + return DirectAllocator{ + .allocator = Allocator{ .allocFn = alloc, .reallocFn = realloc, .freeFn = free, @@ -71,39 +68,39 @@ pub const DirectAllocator = struct { const self = @fieldParentPtr(DirectAllocator, "allocator", allocator); switch (builtin.os) { - Os.linux, Os.macosx, Os.ios => { + Os.linux, + Os.macosx, + Os.ios => { const p = os.posix; - const alloc_size = if(alignment <= os.page_size) n else n + alignment; - const addr = p.mmap(null, alloc_size, p.PROT_READ|p.PROT_WRITE, - p.MAP_PRIVATE|p.MAP_ANONYMOUS, -1, 0); - if(addr == p.MAP_FAILED) return error.OutOfMemory; - - if(alloc_size == n) return @intToPtr(&u8, addr)[0..n]; - + const alloc_size = if (alignment <= os.page_size) n else n + alignment; + const addr = p.mmap(null, alloc_size, p.PROT_READ | p.PROT_WRITE, p.MAP_PRIVATE | p.MAP_ANONYMOUS, -1, 0); + if (addr == p.MAP_FAILED) return error.OutOfMemory; + + if (alloc_size == n) return @intToPtr(&u8, addr)[0..n]; + var aligned_addr = addr & ~usize(alignment - 1); aligned_addr += alignment; - + //We can unmap the unused portions of our mmap, but we must only // pass munmap bytes that exist outside our allocated pages or it // will happily eat us too - + //Since alignment > page_size, we are by definition on a page boundry const unused_start = addr; const unused_len = aligned_addr - 1 - unused_start; var err = p.munmap(unused_start, unused_len); debug.assert(p.getErrno(err) == 0); - + //It is impossible that there is an unoccupied page at the top of our // mmap. - + return @intToPtr(&u8, aligned_addr)[0..n]; }, Os.windows => { const amt = n + alignment + @sizeOf(usize); const heap_handle = self.heap_handle ?? blk: { - const hh = os.windows.HeapCreate(os.windows.HEAP_NO_SERIALIZE, amt, 0) - ?? return error.OutOfMemory; + const hh = os.windows.HeapCreate(os.windows.HEAP_NO_SERIALIZE, amt, 0) ?? return error.OutOfMemory; self.heap_handle = hh; break :blk hh; }; @@ -113,7 +110,7 @@ pub const DirectAllocator = struct { const march_forward_bytes = if (rem == 0) 0 else (alignment - rem); const adjusted_addr = root_addr + march_forward_bytes; const record_addr = adjusted_addr + n; - *@intToPtr(&align(1) usize, record_addr) = root_addr; + @intToPtr(&align(1) usize, record_addr).* = root_addr; return @intToPtr(&u8, adjusted_addr)[0..n]; }, else => @compileError("Unsupported OS"), @@ -124,7 +121,9 @@ pub const DirectAllocator = struct { const self = @fieldParentPtr(DirectAllocator, "allocator", allocator); switch (builtin.os) { - Os.linux, Os.macosx, Os.ios => { + Os.linux, + Os.macosx, + Os.ios => { if (new_size <= old_mem.len) { const base_addr = @ptrToInt(old_mem.ptr); const old_addr_end = base_addr + old_mem.len; @@ -144,13 +143,13 @@ pub const DirectAllocator = struct { Os.windows => { const old_adjusted_addr = @ptrToInt(old_mem.ptr); const old_record_addr = old_adjusted_addr + old_mem.len; - const root_addr = *@intToPtr(&align(1) usize, old_record_addr); + const root_addr = @intToPtr(&align(1) usize, old_record_addr).*; const old_ptr = @intToPtr(os.windows.LPVOID, root_addr); const amt = new_size + alignment + @sizeOf(usize); const new_ptr = os.windows.HeapReAlloc(??self.heap_handle, 0, old_ptr, amt) ?? blk: { if (new_size > old_mem.len) return error.OutOfMemory; const new_record_addr = old_record_addr - new_size + old_mem.len; - *@intToPtr(&align(1) usize, new_record_addr) = root_addr; + @intToPtr(&align(1) usize, new_record_addr).* = root_addr; return old_mem[0..new_size]; }; const offset = old_adjusted_addr - root_addr; @@ -158,7 +157,7 @@ pub const DirectAllocator = struct { const new_adjusted_addr = new_root_addr + offset; assert(new_adjusted_addr % alignment == 0); const new_record_addr = new_adjusted_addr + new_size; - *@intToPtr(&align(1) usize, new_record_addr) = new_root_addr; + @intToPtr(&align(1) usize, new_record_addr).* = new_root_addr; return @intToPtr(&u8, new_adjusted_addr)[0..new_size]; }, else => @compileError("Unsupported OS"), @@ -169,12 +168,14 @@ pub const DirectAllocator = struct { const self = @fieldParentPtr(DirectAllocator, "allocator", allocator); switch (builtin.os) { - Os.linux, Os.macosx, Os.ios => { + Os.linux, + Os.macosx, + Os.ios => { _ = os.posix.munmap(@ptrToInt(bytes.ptr), bytes.len); }, Os.windows => { const record_addr = @ptrToInt(bytes.ptr) + bytes.len; - const root_addr = *@intToPtr(&align(1) usize, record_addr); + const root_addr = @intToPtr(&align(1) usize, record_addr).*; const ptr = @intToPtr(os.windows.LPVOID, root_addr); _ = os.windows.HeapFree(??self.heap_handle, 0, ptr); }, @@ -195,8 +196,8 @@ pub const ArenaAllocator = struct { const BufNode = std.LinkedList([]u8).Node; pub fn init(child_allocator: &Allocator) ArenaAllocator { - return ArenaAllocator { - .allocator = Allocator { + return ArenaAllocator{ + .allocator = Allocator{ .allocFn = alloc, .reallocFn = realloc, .freeFn = free, @@ -228,7 +229,7 @@ pub const ArenaAllocator = struct { const buf = try self.child_allocator.alignedAlloc(u8, @alignOf(BufNode), len); const buf_node_slice = ([]BufNode)(buf[0..@sizeOf(BufNode)]); const buf_node = &buf_node_slice[0]; - *buf_node = BufNode { + buf_node.* = BufNode{ .data = buf, .prev = null, .next = null, @@ -253,7 +254,7 @@ pub const ArenaAllocator = struct { cur_node = try self.createNode(cur_buf.len, n + alignment); continue; } - const result = cur_buf[adjusted_index .. new_end_index]; + const result = cur_buf[adjusted_index..new_end_index]; self.end_index = new_end_index; return result; } @@ -269,7 +270,7 @@ pub const ArenaAllocator = struct { } } - fn free(allocator: &Allocator, bytes: []u8) void { } + fn free(allocator: &Allocator, bytes: []u8) void {} }; pub const FixedBufferAllocator = struct { @@ -278,8 +279,8 @@ pub const FixedBufferAllocator = struct { buffer: []u8, pub fn init(buffer: []u8) FixedBufferAllocator { - return FixedBufferAllocator { - .allocator = Allocator { + return FixedBufferAllocator{ + .allocator = Allocator{ .allocFn = alloc, .reallocFn = realloc, .freeFn = free, @@ -299,7 +300,7 @@ pub const FixedBufferAllocator = struct { if (new_end_index > self.buffer.len) { return error.OutOfMemory; } - const result = self.buffer[adjusted_index .. new_end_index]; + const result = self.buffer[adjusted_index..new_end_index]; self.end_index = new_end_index; return result; @@ -315,7 +316,7 @@ pub const FixedBufferAllocator = struct { } } - fn free(allocator: &Allocator, bytes: []u8) void { } + fn free(allocator: &Allocator, bytes: []u8) void {} }; /// lock free @@ -325,8 +326,8 @@ pub const ThreadSafeFixedBufferAllocator = struct { buffer: []u8, pub fn init(buffer: []u8) ThreadSafeFixedBufferAllocator { - return ThreadSafeFixedBufferAllocator { - .allocator = Allocator { + return ThreadSafeFixedBufferAllocator{ + .allocator = Allocator{ .allocFn = alloc, .reallocFn = realloc, .freeFn = free, @@ -348,8 +349,7 @@ pub const ThreadSafeFixedBufferAllocator = struct { if (new_end_index > self.buffer.len) { return error.OutOfMemory; } - end_index = @cmpxchgWeak(usize, &self.end_index, end_index, new_end_index, - builtin.AtomicOrder.SeqCst, builtin.AtomicOrder.SeqCst) ?? return self.buffer[adjusted_index .. new_end_index]; + end_index = @cmpxchgWeak(usize, &self.end_index, end_index, new_end_index, builtin.AtomicOrder.SeqCst, builtin.AtomicOrder.SeqCst) ?? return self.buffer[adjusted_index..new_end_index]; } } @@ -363,11 +363,9 @@ pub const ThreadSafeFixedBufferAllocator = struct { } } - fn free(allocator: &Allocator, bytes: []u8) void { } + fn free(allocator: &Allocator, bytes: []u8) void {} }; - - test "c_allocator" { if (builtin.link_libc) { var slice = c_allocator.alloc(u8, 50) catch return; @@ -415,8 +413,8 @@ fn testAllocator(allocator: &mem.Allocator) !void { var slice = try allocator.alloc(&i32, 100); for (slice) |*item, i| { - *item = try allocator.create(i32); - **item = i32(i); + item.* = try allocator.create(i32); + item.*.* = i32(i); } for (slice) |item, i| { @@ -434,26 +432,26 @@ fn testAllocator(allocator: &mem.Allocator) !void { fn testAllocatorLargeAlignment(allocator: &mem.Allocator) mem.Allocator.Error!void { //Maybe a platform's page_size is actually the same as or // very near usize? - if(os.page_size << 2 > @maxValue(usize)) return; - + if (os.page_size << 2 > @maxValue(usize)) return; + const USizeShift = @IntType(false, std.math.log2(usize.bit_count)); const large_align = u29(os.page_size << 2); - + var align_mask: usize = undefined; _ = @shlWithOverflow(usize, ~usize(0), USizeShift(@ctz(large_align)), &align_mask); - + var slice = try allocator.allocFn(allocator, 500, large_align); debug.assert(@ptrToInt(slice.ptr) & align_mask == @ptrToInt(slice.ptr)); - + slice = try allocator.reallocFn(allocator, slice, 100, large_align); debug.assert(@ptrToInt(slice.ptr) & align_mask == @ptrToInt(slice.ptr)); - + slice = try allocator.reallocFn(allocator, slice, 5000, large_align); debug.assert(@ptrToInt(slice.ptr) & align_mask == @ptrToInt(slice.ptr)); - + slice = try allocator.reallocFn(allocator, slice, 10, large_align); debug.assert(@ptrToInt(slice.ptr) & align_mask == @ptrToInt(slice.ptr)); - + slice = try allocator.reallocFn(allocator, slice, 20000, large_align); debug.assert(@ptrToInt(slice.ptr) & align_mask == @ptrToInt(slice.ptr)); diff --git a/std/io.zig b/std/io.zig index 7b72af15e439ff763b1b42f29e30be0c614a1f47..7c997fdf428e5ad9486dda37c6f063a2e24447a7 100644 --- a/std/io.zig +++ b/std/io.zig @@ -18,32 +18,17 @@ const is_windows = builtin.os == builtin.Os.windows; const GetStdIoErrs = os.WindowsGetStdHandleErrs; pub fn getStdErr() GetStdIoErrs!File { - const handle = if (is_windows) - try os.windowsGetStdHandle(os.windows.STD_ERROR_HANDLE) - else if (is_posix) - os.posix.STDERR_FILENO - else - unreachable; + const handle = if (is_windows) try os.windowsGetStdHandle(os.windows.STD_ERROR_HANDLE) else if (is_posix) os.posix.STDERR_FILENO else unreachable; return File.openHandle(handle); } pub fn getStdOut() GetStdIoErrs!File { - const handle = if (is_windows) - try os.windowsGetStdHandle(os.windows.STD_OUTPUT_HANDLE) - else if (is_posix) - os.posix.STDOUT_FILENO - else - unreachable; + const handle = if (is_windows) try os.windowsGetStdHandle(os.windows.STD_OUTPUT_HANDLE) else if (is_posix) os.posix.STDOUT_FILENO else unreachable; return File.openHandle(handle); } pub fn getStdIn() GetStdIoErrs!File { - const handle = if (is_windows) - try os.windowsGetStdHandle(os.windows.STD_INPUT_HANDLE) - else if (is_posix) - os.posix.STDIN_FILENO - else - unreachable; + const handle = if (is_windows) try os.windowsGetStdHandle(os.windows.STD_INPUT_HANDLE) else if (is_posix) os.posix.STDIN_FILENO else unreachable; return File.openHandle(handle); } @@ -56,11 +41,9 @@ pub const FileInStream = struct { pub const Stream = InStream(Error); pub fn init(file: &File) FileInStream { - return FileInStream { + return FileInStream{ .file = file, - .stream = Stream { - .readFn = readFn, - }, + .stream = Stream{ .readFn = readFn }, }; } @@ -79,11 +62,9 @@ pub const FileOutStream = struct { pub const Stream = OutStream(Error); pub fn init(file: &File) FileOutStream { - return FileOutStream { + return FileOutStream{ .file = file, - .stream = Stream { - .writeFn = writeFn, - }, + .stream = Stream{ .writeFn = writeFn }, }; } @@ -121,8 +102,7 @@ pub fn InStream(comptime ReadError: type) type { } const new_buf_size = math.min(max_size, actual_buf_len + os.page_size); - if (new_buf_size == actual_buf_len) - return error.StreamTooLong; + if (new_buf_size == actual_buf_len) return error.StreamTooLong; try buffer.resize(new_buf_size); } } @@ -165,9 +145,7 @@ pub fn InStream(comptime ReadError: type) type { /// memory would be greater than `max_size`, returns `error.StreamTooLong`. /// Caller owns returned memory. /// If this function returns an error, the contents from the stream read so far are lost. - pub fn readUntilDelimiterAlloc(self: &Self, allocator: &mem.Allocator, - delimiter: u8, max_size: usize) ![]u8 - { + pub fn readUntilDelimiterAlloc(self: &Self, allocator: &mem.Allocator, delimiter: u8, max_size: usize) ![]u8 { var buf = Buffer.initNull(allocator); defer buf.deinit(); @@ -283,7 +261,7 @@ pub fn BufferedInStream(comptime Error: type) type { pub fn BufferedInStreamCustom(comptime buffer_size: usize, comptime Error: type) type { return struct { const Self = this; - const Stream = InStream(Error); + const Stream = InStream(Error); pub stream: Stream, @@ -294,7 +272,7 @@ pub fn BufferedInStreamCustom(comptime buffer_size: usize, comptime Error: type) end_index: usize, pub fn init(unbuffered_in_stream: &Stream) Self { - return Self { + return Self{ .unbuffered_in_stream = unbuffered_in_stream, .buffer = undefined, @@ -305,9 +283,7 @@ pub fn BufferedInStreamCustom(comptime buffer_size: usize, comptime Error: type) .start_index = buffer_size, .end_index = buffer_size, - .stream = Stream { - .readFn = readFn, - }, + .stream = Stream{ .readFn = readFn }, }; } @@ -368,13 +344,11 @@ pub fn BufferedOutStreamCustom(comptime buffer_size: usize, comptime OutStreamEr index: usize, pub fn init(unbuffered_out_stream: &Stream) Self { - return Self { + return Self{ .unbuffered_out_stream = unbuffered_out_stream, .buffer = undefined, .index = 0, - .stream = Stream { - .writeFn = writeFn, - }, + .stream = Stream{ .writeFn = writeFn }, }; } @@ -416,11 +390,9 @@ pub const BufferOutStream = struct { pub const Stream = OutStream(Error); pub fn init(buffer: &Buffer) BufferOutStream { - return BufferOutStream { + return BufferOutStream{ .buffer = buffer, - .stream = Stream { - .writeFn = writeFn, - }, + .stream = Stream{ .writeFn = writeFn }, }; } @@ -430,7 +402,6 @@ pub const BufferOutStream = struct { } }; - pub const BufferedAtomicFile = struct { atomic_file: os.AtomicFile, file_stream: FileOutStream, @@ -441,7 +412,7 @@ pub const BufferedAtomicFile = struct { var self = try allocator.create(BufferedAtomicFile); errdefer allocator.destroy(self); - *self = BufferedAtomicFile { + self.* = BufferedAtomicFile{ .atomic_file = undefined, .file_stream = undefined, .buffered_stream = undefined, @@ -489,7 +460,7 @@ pub fn readLine(buf: []u8) !usize { '\r' => { // trash the following \n _ = stream.readByte() catch return error.EndOfFile; - return index; + return index; }, '\n' => return index, else => { diff --git a/std/linked_list.zig b/std/linked_list.zig index 45595f3efb9f3512038c34119993bd0441f15986..c6be08171ed7c779d335aa1dcd630556f8b82235 100644 --- a/std/linked_list.zig +++ b/std/linked_list.zig @@ -26,10 +26,10 @@ fn BaseLinkedList(comptime T: type, comptime ParentType: type, comptime field_na data: T, pub fn init(value: &const T) Node { - return Node { + return Node{ .prev = null, .next = null, - .data = *value, + .data = value.*, }; } @@ -45,18 +45,18 @@ fn BaseLinkedList(comptime T: type, comptime ParentType: type, comptime field_na }; first: ?&Node, - last: ?&Node, - len: usize, + last: ?&Node, + len: usize, /// Initialize a linked list. /// /// Returns: /// An empty linked list. pub fn init() Self { - return Self { + return Self{ .first = null, - .last = null, - .len = 0, + .last = null, + .len = 0, }; } @@ -131,7 +131,7 @@ fn BaseLinkedList(comptime T: type, comptime ParentType: type, comptime field_na } else { // Empty list. list.first = new_node; - list.last = new_node; + list.last = new_node; new_node.prev = null; new_node.next = null; @@ -217,7 +217,7 @@ fn BaseLinkedList(comptime T: type, comptime ParentType: type, comptime field_na pub fn createNode(list: &Self, data: &const T, allocator: &Allocator) !&Node { comptime assert(!isIntrusive()); var node = try list.allocateNode(allocator); - *node = Node.init(data); + node.* = Node.init(data); return node; } }; @@ -227,11 +227,11 @@ test "basic linked list test" { const allocator = debug.global_allocator; var list = LinkedList(u32).init(); - var one = try list.createNode(1, allocator); - var two = try list.createNode(2, allocator); + var one = try list.createNode(1, allocator); + var two = try list.createNode(2, allocator); var three = try list.createNode(3, allocator); - var four = try list.createNode(4, allocator); - var five = try list.createNode(5, allocator); + var four = try list.createNode(4, allocator); + var five = try list.createNode(5, allocator); defer { list.destroyNode(one, allocator); list.destroyNode(two, allocator); @@ -240,11 +240,11 @@ test "basic linked list test" { list.destroyNode(five, allocator); } - list.append(two); // {2} - list.append(five); // {2, 5} - list.prepend(one); // {1, 2, 5} - list.insertBefore(five, four); // {1, 2, 4, 5} - list.insertAfter(two, three); // {1, 2, 3, 4, 5} + list.append(two); // {2} + list.append(five); // {2, 5} + list.prepend(one); // {1, 2, 5} + list.insertBefore(five, four); // {1, 2, 4, 5} + list.insertAfter(two, three); // {1, 2, 3, 4, 5} // Traverse forwards. { @@ -266,13 +266,13 @@ test "basic linked list test" { } } - var first = list.popFirst(); // {2, 3, 4, 5} - var last = list.pop(); // {2, 3, 4} - list.remove(three); // {2, 4} + var first = list.popFirst(); // {2, 3, 4, 5} + var last = list.pop(); // {2, 3, 4} + list.remove(three); // {2, 4} - assert ((??list.first).data == 2); - assert ((??list.last ).data == 4); - assert (list.len == 2); + assert((??list.first).data == 2); + assert((??list.last).data == 4); + assert(list.len == 2); } const ElementList = IntrusiveLinkedList(Element, "link"); @@ -285,17 +285,32 @@ test "basic intrusive linked list test" { const allocator = debug.global_allocator; var list = ElementList.init(); - var one = Element { .value = 1, .link = ElementList.Node.initIntrusive() }; - var two = Element { .value = 2, .link = ElementList.Node.initIntrusive() }; - var three = Element { .value = 3, .link = ElementList.Node.initIntrusive() }; - var four = Element { .value = 4, .link = ElementList.Node.initIntrusive() }; - var five = Element { .value = 5, .link = ElementList.Node.initIntrusive() }; + var one = Element{ + .value = 1, + .link = ElementList.Node.initIntrusive(), + }; + var two = Element{ + .value = 2, + .link = ElementList.Node.initIntrusive(), + }; + var three = Element{ + .value = 3, + .link = ElementList.Node.initIntrusive(), + }; + var four = Element{ + .value = 4, + .link = ElementList.Node.initIntrusive(), + }; + var five = Element{ + .value = 5, + .link = ElementList.Node.initIntrusive(), + }; - list.append(&two.link); // {2} - list.append(&five.link); // {2, 5} - list.prepend(&one.link); // {1, 2, 5} - list.insertBefore(&five.link, &four.link); // {1, 2, 4, 5} - list.insertAfter(&two.link, &three.link); // {1, 2, 3, 4, 5} + list.append(&two.link); // {2} + list.append(&five.link); // {2, 5} + list.prepend(&one.link); // {1, 2, 5} + list.insertBefore(&five.link, &four.link); // {1, 2, 4, 5} + list.insertAfter(&two.link, &three.link); // {1, 2, 3, 4, 5} // Traverse forwards. { @@ -317,11 +332,11 @@ test "basic intrusive linked list test" { } } - var first = list.popFirst(); // {2, 3, 4, 5} - var last = list.pop(); // {2, 3, 4} - list.remove(&three.link); // {2, 4} + var first = list.popFirst(); // {2, 3, 4, 5} + var last = list.pop(); // {2, 3, 4} + list.remove(&three.link); // {2, 4} - assert ((??list.first).toData().value == 2); - assert ((??list.last ).toData().value == 4); - assert (list.len == 2); + assert((??list.first).toData().value == 2); + assert((??list.last).toData().value == 4); + assert(list.len == 2); } diff --git a/std/os/index.zig b/std/os/index.zig index 4f1826021fe3b7da387547fb7ec6ab6e26a1e8cf..8728f4a6f681fda1a86dbc131512854cace44dda 100644 --- a/std/os/index.zig +++ b/std/os/index.zig @@ -137,7 +137,7 @@ pub fn getRandomBytes(buf: []u8) !void { } }, Os.zen => { - const randomness = []u8 { + const randomness = []u8{ 42, 1, 7, @@ -265,7 +265,7 @@ pub fn posixRead(fd: i32, buf: []u8) !void { } } -pub const PosixWriteError = error { +pub const PosixWriteError = error{ WouldBlock, FileClosed, DestinationAddressRequired, @@ -310,7 +310,7 @@ pub fn posixWrite(fd: i32, bytes: []const u8) !void { } } -pub const PosixOpenError = error { +pub const PosixOpenError = error{ OutOfMemory, AccessDenied, FileTooBig, @@ -477,7 +477,7 @@ pub fn posixExecve(argv: []const []const u8, env_map: &const BufMap, allocator: return posixExecveErrnoToErr(err); } -pub const PosixExecveError = error { +pub const PosixExecveError = error{ SystemResources, AccessDenied, InvalidExe, @@ -512,7 +512,7 @@ fn posixExecveErrnoToErr(err: usize) PosixExecveError { }; } -pub var linux_aux_raw = []usize {0} ** 38; +pub var linux_aux_raw = []usize{0} ** 38; pub var posix_environ_raw: []&u8 = undefined; /// Caller must free result when done. @@ -667,7 +667,7 @@ pub fn symLink(allocator: &Allocator, existing_path: []const u8, new_path: []con } } -pub const WindowsSymLinkError = error { +pub const WindowsSymLinkError = error{ OutOfMemory, Unexpected, }; @@ -686,7 +686,7 @@ pub fn symLinkWindows(allocator: &Allocator, existing_path: []const u8, new_path } } -pub const PosixSymLinkError = error { +pub const PosixSymLinkError = error{ OutOfMemory, AccessDenied, DiskQuota, @@ -895,7 +895,7 @@ pub const AtomicFile = struct { else => return err, }; - return AtomicFile { + return AtomicFile{ .allocator = allocator, .file = file, .tmp_path = tmp_path, @@ -1087,7 +1087,7 @@ pub fn deleteDir(allocator: &Allocator, dir_path: []const u8) !void { /// removes it. If it cannot be removed because it is a non-empty directory, /// this function recursively removes its entries and then tries again. /// TODO non-recursive implementation -const DeleteTreeError = error { +const DeleteTreeError = error{ OutOfMemory, AccessDenied, FileTooBig, @@ -1217,7 +1217,7 @@ pub const Dir = struct { Os.ios => 0, else => {}, }; - return Dir { + return Dir{ .allocator = allocator, .fd = fd, .darwin_seek = darwin_seek_init, @@ -1294,7 +1294,7 @@ pub const Dir = struct { posix.DT_WHT => Entry.Kind.Whiteout, else => Entry.Kind.Unknown, }; - return Entry { + return Entry{ .name = name, .kind = entry_kind, }; @@ -1355,7 +1355,7 @@ pub const Dir = struct { posix.DT_SOCK => Entry.Kind.UnixDomainSocket, else => Entry.Kind.Unknown, }; - return Entry { + return Entry{ .name = name, .kind = entry_kind, }; @@ -1465,7 +1465,7 @@ pub fn posix_setregid(rgid: u32, egid: u32) !void { }; } -pub const WindowsGetStdHandleErrs = error { +pub const WindowsGetStdHandleErrs = error{ NoStdHandles, Unexpected, }; @@ -1489,7 +1489,7 @@ pub const ArgIteratorPosix = struct { count: usize, pub fn init() ArgIteratorPosix { - return ArgIteratorPosix { + return ArgIteratorPosix{ .index = 0, .count = raw.len, }; @@ -1522,16 +1522,14 @@ pub const ArgIteratorWindows = struct { quote_count: usize, seen_quote_count: usize, - pub const NextError = error { - OutOfMemory, - }; + pub const NextError = error{OutOfMemory}; pub fn init() ArgIteratorWindows { return initWithCmdLine(windows.GetCommandLineA()); } pub fn initWithCmdLine(cmd_line: &const u8) ArgIteratorWindows { - return ArgIteratorWindows { + return ArgIteratorWindows{ .index = 0, .cmd_line = cmd_line, .in_quote = false, @@ -1676,9 +1674,7 @@ pub const ArgIterator = struct { inner: InnerType, pub fn init() ArgIterator { - return ArgIterator { - .inner = InnerType.init(), - }; + return ArgIterator{ .inner = InnerType.init() }; } pub const NextError = ArgIteratorWindows.NextError; @@ -1757,33 +1753,33 @@ pub fn argsFree(allocator: &mem.Allocator, args_alloc: []const []u8) void { } test "windows arg parsing" { - testWindowsCmdLine(c"a b\tc d", [][]const u8 { + testWindowsCmdLine(c"a b\tc d", [][]const u8{ "a", "b", "c", "d", }); - testWindowsCmdLine(c"\"abc\" d e", [][]const u8 { + testWindowsCmdLine(c"\"abc\" d e", [][]const u8{ "abc", "d", "e", }); - testWindowsCmdLine(c"a\\\\\\b d\"e f\"g h", [][]const u8 { + testWindowsCmdLine(c"a\\\\\\b d\"e f\"g h", [][]const u8{ "a\\\\\\b", "de fg", "h", }); - testWindowsCmdLine(c"a\\\\\\\"b c d", [][]const u8 { + testWindowsCmdLine(c"a\\\\\\\"b c d", [][]const u8{ "a\\\"b", "c", "d", }); - testWindowsCmdLine(c"a\\\\\\\\\"b c\" d e", [][]const u8 { + testWindowsCmdLine(c"a\\\\\\\\\"b c\" d e", [][]const u8{ "a\\\\b c", "d", "e", }); - testWindowsCmdLine(c"a b\tc \"d f", [][]const u8 { + testWindowsCmdLine(c"a b\tc \"d f", [][]const u8{ "a", "b", "c", @@ -1791,7 +1787,7 @@ test "windows arg parsing" { "f", }); - testWindowsCmdLine(c"\".\\..\\zig-cache\\build\" \"bin\\zig.exe\" \".\\..\" \".\\..\\zig-cache\" \"--help\"", [][]const u8 { + testWindowsCmdLine(c"\".\\..\\zig-cache\\build\" \"bin\\zig.exe\" \".\\..\" \".\\..\\zig-cache\" \"--help\"", [][]const u8{ ".\\..\\zig-cache\\build", "bin\\zig.exe", ".\\..", @@ -1811,7 +1807,7 @@ fn testWindowsCmdLine(input_cmd_line: &const u8, expected_args: []const []const // TODO make this a build variable that you can set const unexpected_error_tracing = false; -const UnexpectedError = error { +const UnexpectedError = error{ /// The Operating System returned an undocumented error code. Unexpected, }; @@ -1950,7 +1946,7 @@ pub fn isTty(handle: FileHandle) bool { } } -pub const PosixSocketError = error { +pub const PosixSocketError = error{ /// Permission to create a socket of the specified type and/or /// pro‐tocol is denied. PermissionDenied, @@ -1992,7 +1988,7 @@ pub fn posixSocket(domain: u32, socket_type: u32, protocol: u32) !i32 { } } -pub const PosixBindError = error { +pub const PosixBindError = error{ /// The address is protected, and the user is not the superuser. /// For UNIX domain sockets: Search permission is denied on a component /// of the path prefix. @@ -2065,7 +2061,7 @@ pub fn posixBind(fd: i32, addr: &const posix.sockaddr) PosixBindError!void { } } -const PosixListenError = error { +const PosixListenError = error{ /// Another socket is already listening on the same port. /// For Internet domain sockets, the socket referred to by sockfd had not previously /// been bound to an address and, upon attempting to bind it to an ephemeral port, it @@ -2098,7 +2094,7 @@ pub fn posixListen(sockfd: i32, backlog: u32) PosixListenError!void { } } -pub const PosixAcceptError = error { +pub const PosixAcceptError = error{ /// The socket is marked nonblocking and no connections are present to be accepted. WouldBlock, @@ -2165,7 +2161,7 @@ pub fn posixAccept(fd: i32, addr: &posix.sockaddr, flags: u32) PosixAcceptError! } } -pub const LinuxEpollCreateError = error { +pub const LinuxEpollCreateError = error{ /// Invalid value specified in flags. InvalidSyscall, @@ -2198,7 +2194,7 @@ pub fn linuxEpollCreate(flags: u32) LinuxEpollCreateError!i32 { } } -pub const LinuxEpollCtlError = error { +pub const LinuxEpollCtlError = error{ /// epfd or fd is not a valid file descriptor. InvalidFileDescriptor, @@ -2271,7 +2267,7 @@ pub fn linuxEpollWait(epfd: i32, events: []linux.epoll_event, timeout: i32) usiz } } -pub const PosixGetSockNameError = error { +pub const PosixGetSockNameError = error{ /// Insufficient resources were available in the system to perform the operation. SystemResources, @@ -2295,7 +2291,7 @@ pub fn posixGetSockName(sockfd: i32) PosixGetSockNameError!posix.sockaddr { } } -pub const PosixConnectError = error { +pub const PosixConnectError = error{ /// For UNIX domain sockets, which are identified by pathname: Write permission is denied on the socket /// file, or search permission is denied for one of the directories in the path prefix. /// or @@ -2484,7 +2480,7 @@ pub const Thread = struct { } }; -pub const SpawnThreadError = error { +pub const SpawnThreadError = error{ /// A system-imposed limit on the number of threads was encountered. /// There are a number of limits that may trigger this error: /// * the RLIMIT_NPROC soft resource limit (set via setrlimit(2)), @@ -2532,7 +2528,7 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!&Thread if (@sizeOf(Context) == 0) { return startFn({}); } else { - return startFn(*@ptrCast(&Context, @alignCast(@alignOf(Context), arg))); + return startFn(@ptrCast(&Context, @alignCast(@alignOf(Context), arg)).*); } } }; @@ -2562,7 +2558,7 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!&Thread if (@sizeOf(Context) == 0) { return startFn({}); } else { - return startFn(*@intToPtr(&const Context, ctx_addr)); + return startFn(@intToPtr(&const Context, ctx_addr).*); } } extern fn posixThreadMain(ctx: ?&c_void) ?&c_void { @@ -2570,7 +2566,7 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!&Thread _ = startFn({}); return null; } else { - _ = startFn(*@ptrCast(&const Context, @alignCast(@alignOf(Context), ctx))); + _ = startFn(@ptrCast(&const Context, @alignCast(@alignOf(Context), ctx)).*); return null; } } @@ -2590,7 +2586,7 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!&Thread stack_end -= stack_end % @alignOf(Context); assert(stack_end >= stack_addr); const context_ptr = @alignCast(@alignOf(Context), @intToPtr(&Context, stack_end)); - *context_ptr = context; + context_ptr.* = context; arg = stack_end; } diff --git a/std/os/linux/index.zig b/std/os/linux/index.zig index 368f074b9b39fff7b2d7b4fda62a24dea547aa33..4e0e9ee5d5f5db550b7da0f5b0878dede9cfb09e 100644 --- a/std/os/linux/index.zig +++ b/std/os/linux/index.zig @@ -30,96 +30,95 @@ pub const FUTEX_PRIVATE_FLAG = 128; pub const FUTEX_CLOCK_REALTIME = 256; - -pub const PROT_NONE = 0; -pub const PROT_READ = 1; -pub const PROT_WRITE = 2; -pub const PROT_EXEC = 4; +pub const PROT_NONE = 0; +pub const PROT_READ = 1; +pub const PROT_WRITE = 2; +pub const PROT_EXEC = 4; pub const PROT_GROWSDOWN = 0x01000000; -pub const PROT_GROWSUP = 0x02000000; +pub const PROT_GROWSUP = 0x02000000; -pub const MAP_FAILED = @maxValue(usize); -pub const MAP_SHARED = 0x01; -pub const MAP_PRIVATE = 0x02; -pub const MAP_TYPE = 0x0f; -pub const MAP_FIXED = 0x10; -pub const MAP_ANONYMOUS = 0x20; -pub const MAP_NORESERVE = 0x4000; -pub const MAP_GROWSDOWN = 0x0100; -pub const MAP_DENYWRITE = 0x0800; +pub const MAP_FAILED = @maxValue(usize); +pub const MAP_SHARED = 0x01; +pub const MAP_PRIVATE = 0x02; +pub const MAP_TYPE = 0x0f; +pub const MAP_FIXED = 0x10; +pub const MAP_ANONYMOUS = 0x20; +pub const MAP_NORESERVE = 0x4000; +pub const MAP_GROWSDOWN = 0x0100; +pub const MAP_DENYWRITE = 0x0800; pub const MAP_EXECUTABLE = 0x1000; -pub const MAP_LOCKED = 0x2000; -pub const MAP_POPULATE = 0x8000; -pub const MAP_NONBLOCK = 0x10000; -pub const MAP_STACK = 0x20000; -pub const MAP_HUGETLB = 0x40000; -pub const MAP_FILE = 0; +pub const MAP_LOCKED = 0x2000; +pub const MAP_POPULATE = 0x8000; +pub const MAP_NONBLOCK = 0x10000; +pub const MAP_STACK = 0x20000; +pub const MAP_HUGETLB = 0x40000; +pub const MAP_FILE = 0; pub const F_OK = 0; pub const X_OK = 1; pub const W_OK = 2; pub const R_OK = 4; -pub const WNOHANG = 1; -pub const WUNTRACED = 2; -pub const WSTOPPED = 2; -pub const WEXITED = 4; +pub const WNOHANG = 1; +pub const WUNTRACED = 2; +pub const WSTOPPED = 2; +pub const WEXITED = 4; pub const WCONTINUED = 8; -pub const WNOWAIT = 0x1000000; +pub const WNOWAIT = 0x1000000; -pub const SA_NOCLDSTOP = 1; -pub const SA_NOCLDWAIT = 2; -pub const SA_SIGINFO = 4; -pub const SA_ONSTACK = 0x08000000; -pub const SA_RESTART = 0x10000000; -pub const SA_NODEFER = 0x40000000; -pub const SA_RESETHAND = 0x80000000; -pub const SA_RESTORER = 0x04000000; +pub const SA_NOCLDSTOP = 1; +pub const SA_NOCLDWAIT = 2; +pub const SA_SIGINFO = 4; +pub const SA_ONSTACK = 0x08000000; +pub const SA_RESTART = 0x10000000; +pub const SA_NODEFER = 0x40000000; +pub const SA_RESETHAND = 0x80000000; +pub const SA_RESTORER = 0x04000000; -pub const SIGHUP = 1; -pub const SIGINT = 2; -pub const SIGQUIT = 3; -pub const SIGILL = 4; -pub const SIGTRAP = 5; -pub const SIGABRT = 6; -pub const SIGIOT = SIGABRT; -pub const SIGBUS = 7; -pub const SIGFPE = 8; -pub const SIGKILL = 9; -pub const SIGUSR1 = 10; -pub const SIGSEGV = 11; -pub const SIGUSR2 = 12; -pub const SIGPIPE = 13; -pub const SIGALRM = 14; -pub const SIGTERM = 15; +pub const SIGHUP = 1; +pub const SIGINT = 2; +pub const SIGQUIT = 3; +pub const SIGILL = 4; +pub const SIGTRAP = 5; +pub const SIGABRT = 6; +pub const SIGIOT = SIGABRT; +pub const SIGBUS = 7; +pub const SIGFPE = 8; +pub const SIGKILL = 9; +pub const SIGUSR1 = 10; +pub const SIGSEGV = 11; +pub const SIGUSR2 = 12; +pub const SIGPIPE = 13; +pub const SIGALRM = 14; +pub const SIGTERM = 15; pub const SIGSTKFLT = 16; -pub const SIGCHLD = 17; -pub const SIGCONT = 18; -pub const SIGSTOP = 19; -pub const SIGTSTP = 20; -pub const SIGTTIN = 21; -pub const SIGTTOU = 22; -pub const SIGURG = 23; -pub const SIGXCPU = 24; -pub const SIGXFSZ = 25; +pub const SIGCHLD = 17; +pub const SIGCONT = 18; +pub const SIGSTOP = 19; +pub const SIGTSTP = 20; +pub const SIGTTIN = 21; +pub const SIGTTOU = 22; +pub const SIGURG = 23; +pub const SIGXCPU = 24; +pub const SIGXFSZ = 25; pub const SIGVTALRM = 26; -pub const SIGPROF = 27; -pub const SIGWINCH = 28; -pub const SIGIO = 29; -pub const SIGPOLL = 29; -pub const SIGPWR = 30; -pub const SIGSYS = 31; +pub const SIGPROF = 27; +pub const SIGWINCH = 28; +pub const SIGIO = 29; +pub const SIGPOLL = 29; +pub const SIGPWR = 30; +pub const SIGSYS = 31; pub const SIGUNUSED = SIGSYS; pub const O_RDONLY = 0o0; pub const O_WRONLY = 0o1; -pub const O_RDWR = 0o2; +pub const O_RDWR = 0o2; pub const SEEK_SET = 0; pub const SEEK_CUR = 1; pub const SEEK_END = 2; -pub const SIG_BLOCK = 0; +pub const SIG_BLOCK = 0; pub const SIG_UNBLOCK = 1; pub const SIG_SETMASK = 2; @@ -408,7 +407,6 @@ pub const DT_LNK = 10; pub const DT_SOCK = 12; pub const DT_WHT = 14; - pub const TCGETS = 0x5401; pub const TCSETS = 0x5402; pub const TCSETSW = 0x5403; @@ -539,23 +537,23 @@ pub const MS_BIND = 4096; pub const MS_MOVE = 8192; pub const MS_REC = 16384; pub const MS_SILENT = 32768; -pub const MS_POSIXACL = (1<<16); -pub const MS_UNBINDABLE = (1<<17); -pub const MS_PRIVATE = (1<<18); -pub const MS_SLAVE = (1<<19); -pub const MS_SHARED = (1<<20); -pub const MS_RELATIME = (1<<21); -pub const MS_KERNMOUNT = (1<<22); -pub const MS_I_VERSION = (1<<23); -pub const MS_STRICTATIME = (1<<24); -pub const MS_LAZYTIME = (1<<25); -pub const MS_NOREMOTELOCK = (1<<27); -pub const MS_NOSEC = (1<<28); -pub const MS_BORN = (1<<29); -pub const MS_ACTIVE = (1<<30); -pub const MS_NOUSER = (1<<31); +pub const MS_POSIXACL = (1 << 16); +pub const MS_UNBINDABLE = (1 << 17); +pub const MS_PRIVATE = (1 << 18); +pub const MS_SLAVE = (1 << 19); +pub const MS_SHARED = (1 << 20); +pub const MS_RELATIME = (1 << 21); +pub const MS_KERNMOUNT = (1 << 22); +pub const MS_I_VERSION = (1 << 23); +pub const MS_STRICTATIME = (1 << 24); +pub const MS_LAZYTIME = (1 << 25); +pub const MS_NOREMOTELOCK = (1 << 27); +pub const MS_NOSEC = (1 << 28); +pub const MS_BORN = (1 << 29); +pub const MS_ACTIVE = (1 << 30); +pub const MS_NOUSER = (1 << 31); -pub const MS_RMT_MASK = (MS_RDONLY|MS_SYNCHRONOUS|MS_MANDLOCK|MS_I_VERSION|MS_LAZYTIME); +pub const MS_RMT_MASK = (MS_RDONLY | MS_SYNCHRONOUS | MS_MANDLOCK | MS_I_VERSION | MS_LAZYTIME); pub const MS_MGC_VAL = 0xc0ed0000; pub const MS_MGC_MSK = 0xffff0000; @@ -565,7 +563,6 @@ pub const MNT_DETACH = 2; pub const MNT_EXPIRE = 4; pub const UMOUNT_NOFOLLOW = 8; - pub const S_IFMT = 0o170000; pub const S_IFDIR = 0o040000; @@ -626,15 +623,30 @@ pub const TFD_CLOEXEC = O_CLOEXEC; pub const TFD_TIMER_ABSTIME = 1; pub const TFD_TIMER_CANCEL_ON_SET = (1 << 1); -fn unsigned(s: i32) u32 { return @bitCast(u32, s); } -fn signed(s: u32) i32 { return @bitCast(i32, s); } -pub fn WEXITSTATUS(s: i32) i32 { return signed((unsigned(s) & 0xff00) >> 8); } -pub fn WTERMSIG(s: i32) i32 { return signed(unsigned(s) & 0x7f); } -pub fn WSTOPSIG(s: i32) i32 { return WEXITSTATUS(s); } -pub fn WIFEXITED(s: i32) bool { return WTERMSIG(s) == 0; } -pub fn WIFSTOPPED(s: i32) bool { return (u16)(((unsigned(s)&0xffff)*%0x10001)>>8) > 0x7f00; } -pub fn WIFSIGNALED(s: i32) bool { return (unsigned(s)&0xffff)-%1 < 0xff; } - +fn unsigned(s: i32) u32 { + return @bitCast(u32, s); +} +fn signed(s: u32) i32 { + return @bitCast(i32, s); +} +pub fn WEXITSTATUS(s: i32) i32 { + return signed((unsigned(s) & 0xff00) >> 8); +} +pub fn WTERMSIG(s: i32) i32 { + return signed(unsigned(s) & 0x7f); +} +pub fn WSTOPSIG(s: i32) i32 { + return WEXITSTATUS(s); +} +pub fn WIFEXITED(s: i32) bool { + return WTERMSIG(s) == 0; +} +pub fn WIFSTOPPED(s: i32) bool { + return (u16)(((unsigned(s) & 0xffff) *% 0x10001) >> 8) > 0x7f00; +} +pub fn WIFSIGNALED(s: i32) bool { + return (unsigned(s) & 0xffff) -% 1 < 0xff; +} pub const winsize = extern struct { ws_row: u16, @@ -707,8 +719,7 @@ pub fn umount2(special: &const u8, flags: u32) usize { } pub fn mmap(address: ?&u8, length: usize, prot: usize, flags: u32, fd: i32, offset: isize) usize { - return syscall6(SYS_mmap, @ptrToInt(address), length, prot, flags, usize(fd), - @bitCast(usize, offset)); + return syscall6(SYS_mmap, @ptrToInt(address), length, prot, flags, usize(fd), @bitCast(usize, offset)); } pub fn munmap(address: usize, length: usize) usize { @@ -812,7 +823,8 @@ pub fn clock_gettime(clk_id: i32, tp: ×pec) usize { if (@ptrToInt(f) != 0) { const rc = f(clk_id, tp); switch (rc) { - 0, @bitCast(usize, isize(-EINVAL)) => return rc, + 0, + @bitCast(usize, isize(-EINVAL)) => return rc, else => {}, } } @@ -823,8 +835,7 @@ var vdso_clock_gettime = init_vdso_clock_gettime; extern fn init_vdso_clock_gettime(clk: i32, ts: ×pec) usize { const addr = vdso.lookup(VDSO_CGT_VER, VDSO_CGT_SYM); var f = @intToPtr(@typeOf(init_vdso_clock_gettime), addr); - _ = @cmpxchgStrong(@typeOf(init_vdso_clock_gettime), &vdso_clock_gettime, init_vdso_clock_gettime, f, - builtin.AtomicOrder.Monotonic, builtin.AtomicOrder.Monotonic); + _ = @cmpxchgStrong(@typeOf(init_vdso_clock_gettime), &vdso_clock_gettime, init_vdso_clock_gettime, f, builtin.AtomicOrder.Monotonic, builtin.AtomicOrder.Monotonic); if (@ptrToInt(f) == 0) return @bitCast(usize, isize(-ENOSYS)); return f(clk, ts); } @@ -918,18 +929,18 @@ pub fn getpid() i32 { } pub fn sigprocmask(flags: u32, noalias set: &const sigset_t, noalias oldset: ?&sigset_t) usize { - return syscall4(SYS_rt_sigprocmask, flags, @ptrToInt(set), @ptrToInt(oldset), NSIG/8); + return syscall4(SYS_rt_sigprocmask, flags, @ptrToInt(set), @ptrToInt(oldset), NSIG / 8); } pub fn sigaction(sig: u6, noalias act: &const Sigaction, noalias oact: ?&Sigaction) usize { assert(sig >= 1); assert(sig != SIGKILL); assert(sig != SIGSTOP); - var ksa = k_sigaction { + var ksa = k_sigaction{ .handler = act.handler, .flags = act.flags | SA_RESTORER, .mask = undefined, - .restorer = @ptrCast(extern fn()void, restore_rt), + .restorer = @ptrCast(extern fn() void, restore_rt), }; var ksa_old: k_sigaction = undefined; @memcpy(@ptrCast(&u8, &ksa.mask), @ptrCast(&const u8, &act.mask), 8); @@ -952,22 +963,22 @@ const all_mask = []usize{@maxValue(usize)}; const app_mask = []usize{0xfffffffc7fffffff}; const k_sigaction = extern struct { - handler: extern fn(i32)void, + handler: extern fn(i32) void, flags: usize, - restorer: extern fn()void, + restorer: extern fn() void, mask: [2]u32, }; /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. pub const Sigaction = struct { - handler: extern fn(i32)void, + handler: extern fn(i32) void, mask: sigset_t, flags: u32, }; -pub const SIG_ERR = @intToPtr(extern fn(i32)void, @maxValue(usize)); -pub const SIG_DFL = @intToPtr(extern fn(i32)void, 0); -pub const SIG_IGN = @intToPtr(extern fn(i32)void, 1); +pub const SIG_ERR = @intToPtr(extern fn(i32) void, @maxValue(usize)); +pub const SIG_DFL = @intToPtr(extern fn(i32) void, 0); +pub const SIG_IGN = @intToPtr(extern fn(i32) void, 1); pub const empty_sigset = []usize{0} ** sigset_t.len; pub fn raise(sig: i32) usize { @@ -980,25 +991,25 @@ pub fn raise(sig: i32) usize { } fn blockAllSignals(set: &sigset_t) void { - _ = syscall4(SYS_rt_sigprocmask, SIG_BLOCK, @ptrToInt(&all_mask), @ptrToInt(set), NSIG/8); + _ = syscall4(SYS_rt_sigprocmask, SIG_BLOCK, @ptrToInt(&all_mask), @ptrToInt(set), NSIG / 8); } fn blockAppSignals(set: &sigset_t) void { - _ = syscall4(SYS_rt_sigprocmask, SIG_BLOCK, @ptrToInt(&app_mask), @ptrToInt(set), NSIG/8); + _ = syscall4(SYS_rt_sigprocmask, SIG_BLOCK, @ptrToInt(&app_mask), @ptrToInt(set), NSIG / 8); } fn restoreSignals(set: &sigset_t) void { - _ = syscall4(SYS_rt_sigprocmask, SIG_SETMASK, @ptrToInt(set), 0, NSIG/8); + _ = syscall4(SYS_rt_sigprocmask, SIG_SETMASK, @ptrToInt(set), 0, NSIG / 8); } pub fn sigaddset(set: &sigset_t, sig: u6) void { const s = sig - 1; - (*set)[usize(s) / usize.bit_count] |= usize(1) << (s & (usize.bit_count - 1)); + (set.*)[usize(s) / usize.bit_count] |= usize(1) << (s & (usize.bit_count - 1)); } pub fn sigismember(set: &const sigset_t, sig: u6) bool { const s = sig - 1; - return ((*set)[usize(s) / usize.bit_count] & (usize(1) << (s & (usize.bit_count - 1)))) != 0; + return ((set.*)[usize(s) / usize.bit_count] & (usize(1) << (s & (usize.bit_count - 1)))) != 0; } pub const in_port_t = u16; @@ -1062,9 +1073,7 @@ pub fn recvmsg(fd: i32, msg: &msghdr, flags: u32) usize { return syscall3(SYS_recvmsg, usize(fd), @ptrToInt(msg), flags); } -pub fn recvfrom(fd: i32, noalias buf: &u8, len: usize, flags: u32, - noalias addr: ?&sockaddr, noalias alen: ?&socklen_t) usize -{ +pub fn recvfrom(fd: i32, noalias buf: &u8, len: usize, flags: u32, noalias addr: ?&sockaddr, noalias alen: ?&socklen_t) usize { return syscall6(SYS_recvfrom, usize(fd), @ptrToInt(buf), len, flags, @ptrToInt(addr), @ptrToInt(alen)); } @@ -1132,25 +1141,16 @@ pub fn fgetxattr(fd: usize, name: &const u8, value: &void, size: usize) usize { return syscall4(SYS_lgetxattr, fd, @ptrToInt(name), @ptrToInt(value), size); } -pub fn setxattr(path: &const u8, name: &const u8, value: &const void, - size: usize, flags: usize) usize { - - return syscall5(SYS_setxattr, @ptrToInt(path), @ptrToInt(name), @ptrToInt(value), - size, flags); +pub fn setxattr(path: &const u8, name: &const u8, value: &const void, size: usize, flags: usize) usize { + return syscall5(SYS_setxattr, @ptrToInt(path), @ptrToInt(name), @ptrToInt(value), size, flags); } -pub fn lsetxattr(path: &const u8, name: &const u8, value: &const void, - size: usize, flags: usize) usize { - - return syscall5(SYS_lsetxattr, @ptrToInt(path), @ptrToInt(name), @ptrToInt(value), - size, flags); +pub fn lsetxattr(path: &const u8, name: &const u8, value: &const void, size: usize, flags: usize) usize { + return syscall5(SYS_lsetxattr, @ptrToInt(path), @ptrToInt(name), @ptrToInt(value), size, flags); } -pub fn fsetxattr(fd: usize, name: &const u8, value: &const void, - size: usize, flags: usize) usize { - - return syscall5(SYS_fsetxattr, fd, @ptrToInt(name), @ptrToInt(value), - size, flags); +pub fn fsetxattr(fd: usize, name: &const u8, value: &const void, size: usize, flags: usize) usize { + return syscall5(SYS_fsetxattr, fd, @ptrToInt(name), @ptrToInt(value), size, flags); } pub fn removexattr(path: &const u8, name: &const u8) usize { @@ -1199,7 +1199,7 @@ pub fn timerfd_create(clockid: i32, flags: u32) usize { pub const itimerspec = extern struct { it_interval: timespec, - it_value: timespec + it_value: timespec, }; pub fn timerfd_gettime(fd: i32, curr_value: &itimerspec) usize { @@ -1211,30 +1211,30 @@ pub fn timerfd_settime(fd: i32, flags: u32, new_value: &const itimerspec, old_va } pub const _LINUX_CAPABILITY_VERSION_1 = 0x19980330; -pub const _LINUX_CAPABILITY_U32S_1 = 1; +pub const _LINUX_CAPABILITY_U32S_1 = 1; pub const _LINUX_CAPABILITY_VERSION_2 = 0x20071026; -pub const _LINUX_CAPABILITY_U32S_2 = 2; +pub const _LINUX_CAPABILITY_U32S_2 = 2; pub const _LINUX_CAPABILITY_VERSION_3 = 0x20080522; -pub const _LINUX_CAPABILITY_U32S_3 = 2; +pub const _LINUX_CAPABILITY_U32S_3 = 2; -pub const VFS_CAP_REVISION_MASK = 0xFF000000; -pub const VFS_CAP_REVISION_SHIFT = 24; -pub const VFS_CAP_FLAGS_MASK = ~VFS_CAP_REVISION_MASK; +pub const VFS_CAP_REVISION_MASK = 0xFF000000; +pub const VFS_CAP_REVISION_SHIFT = 24; +pub const VFS_CAP_FLAGS_MASK = ~VFS_CAP_REVISION_MASK; pub const VFS_CAP_FLAGS_EFFECTIVE = 0x000001; pub const VFS_CAP_REVISION_1 = 0x01000000; -pub const VFS_CAP_U32_1 = 1; -pub const XATTR_CAPS_SZ_1 = @sizeOf(u32)*(1 + 2*VFS_CAP_U32_1); +pub const VFS_CAP_U32_1 = 1; +pub const XATTR_CAPS_SZ_1 = @sizeOf(u32) * (1 + 2 * VFS_CAP_U32_1); pub const VFS_CAP_REVISION_2 = 0x02000000; -pub const VFS_CAP_U32_2 = 2; -pub const XATTR_CAPS_SZ_2 = @sizeOf(u32)*(1 + 2*VFS_CAP_U32_2); +pub const VFS_CAP_U32_2 = 2; +pub const XATTR_CAPS_SZ_2 = @sizeOf(u32) * (1 + 2 * VFS_CAP_U32_2); -pub const XATTR_CAPS_SZ = XATTR_CAPS_SZ_2; -pub const VFS_CAP_U32 = VFS_CAP_U32_2; -pub const VFS_CAP_REVISION = VFS_CAP_REVISION_2; +pub const XATTR_CAPS_SZ = XATTR_CAPS_SZ_2; +pub const VFS_CAP_U32 = VFS_CAP_U32_2; +pub const VFS_CAP_REVISION = VFS_CAP_REVISION_2; pub const vfs_cap_data = extern struct { //all of these are mandated as little endian @@ -1245,49 +1245,48 @@ pub const vfs_cap_data = extern struct { }; magic_etc: u32, - data: [VFS_CAP_U32]Data, + data: [VFS_CAP_U32]Data, }; - -pub const CAP_CHOWN = 0; -pub const CAP_DAC_OVERRIDE = 1; -pub const CAP_DAC_READ_SEARCH = 2; -pub const CAP_FOWNER = 3; -pub const CAP_FSETID = 4; -pub const CAP_KILL = 5; -pub const CAP_SETGID = 6; -pub const CAP_SETUID = 7; -pub const CAP_SETPCAP = 8; -pub const CAP_LINUX_IMMUTABLE = 9; -pub const CAP_NET_BIND_SERVICE = 10; -pub const CAP_NET_BROADCAST = 11; -pub const CAP_NET_ADMIN = 12; -pub const CAP_NET_RAW = 13; -pub const CAP_IPC_LOCK = 14; -pub const CAP_IPC_OWNER = 15; -pub const CAP_SYS_MODULE = 16; -pub const CAP_SYS_RAWIO = 17; -pub const CAP_SYS_CHROOT = 18; -pub const CAP_SYS_PTRACE = 19; -pub const CAP_SYS_PACCT = 20; -pub const CAP_SYS_ADMIN = 21; -pub const CAP_SYS_BOOT = 22; -pub const CAP_SYS_NICE = 23; -pub const CAP_SYS_RESOURCE = 24; -pub const CAP_SYS_TIME = 25; -pub const CAP_SYS_TTY_CONFIG = 26; -pub const CAP_MKNOD = 27; -pub const CAP_LEASE = 28; -pub const CAP_AUDIT_WRITE = 29; -pub const CAP_AUDIT_CONTROL = 30; -pub const CAP_SETFCAP = 31; -pub const CAP_MAC_OVERRIDE = 32; -pub const CAP_MAC_ADMIN = 33; -pub const CAP_SYSLOG = 34; -pub const CAP_WAKE_ALARM = 35; -pub const CAP_BLOCK_SUSPEND = 36; -pub const CAP_AUDIT_READ = 37; -pub const CAP_LAST_CAP = CAP_AUDIT_READ; +pub const CAP_CHOWN = 0; +pub const CAP_DAC_OVERRIDE = 1; +pub const CAP_DAC_READ_SEARCH = 2; +pub const CAP_FOWNER = 3; +pub const CAP_FSETID = 4; +pub const CAP_KILL = 5; +pub const CAP_SETGID = 6; +pub const CAP_SETUID = 7; +pub const CAP_SETPCAP = 8; +pub const CAP_LINUX_IMMUTABLE = 9; +pub const CAP_NET_BIND_SERVICE = 10; +pub const CAP_NET_BROADCAST = 11; +pub const CAP_NET_ADMIN = 12; +pub const CAP_NET_RAW = 13; +pub const CAP_IPC_LOCK = 14; +pub const CAP_IPC_OWNER = 15; +pub const CAP_SYS_MODULE = 16; +pub const CAP_SYS_RAWIO = 17; +pub const CAP_SYS_CHROOT = 18; +pub const CAP_SYS_PTRACE = 19; +pub const CAP_SYS_PACCT = 20; +pub const CAP_SYS_ADMIN = 21; +pub const CAP_SYS_BOOT = 22; +pub const CAP_SYS_NICE = 23; +pub const CAP_SYS_RESOURCE = 24; +pub const CAP_SYS_TIME = 25; +pub const CAP_SYS_TTY_CONFIG = 26; +pub const CAP_MKNOD = 27; +pub const CAP_LEASE = 28; +pub const CAP_AUDIT_WRITE = 29; +pub const CAP_AUDIT_CONTROL = 30; +pub const CAP_SETFCAP = 31; +pub const CAP_MAC_OVERRIDE = 32; +pub const CAP_MAC_ADMIN = 33; +pub const CAP_SYSLOG = 34; +pub const CAP_WAKE_ALARM = 35; +pub const CAP_BLOCK_SUSPEND = 36; +pub const CAP_AUDIT_READ = 37; +pub const CAP_LAST_CAP = CAP_AUDIT_READ; pub fn cap_valid(u8: x) bool { return x >= 0 and x <= CAP_LAST_CAP; diff --git a/std/special/bootstrap.zig b/std/special/bootstrap.zig index 1dc7e248696502dc22432cd6a54bf56e462d512a..056ab35003812c7fbd279ffb814f6a317f82de1d 100644 --- a/std/special/bootstrap.zig +++ b/std/special/bootstrap.zig @@ -27,10 +27,10 @@ extern fn zen_start() noreturn { nakedcc fn _start() noreturn { switch (builtin.arch) { builtin.Arch.x86_64 => { - argc_ptr = asm("lea (%%rsp), %[argc]": [argc] "=r" (-> &usize)); + argc_ptr = asm ("lea (%%rsp), %[argc]" : [argc] "=r" (-> &usize)); }, builtin.Arch.i386 => { - argc_ptr = asm("lea (%%esp), %[argc]": [argc] "=r" (-> &usize)); + argc_ptr = asm ("lea (%%esp), %[argc]" : [argc] "=r" (-> &usize)); }, else => @compileError("unsupported arch"), } @@ -46,7 +46,7 @@ extern fn WinMainCRTStartup() noreturn { } fn posixCallMainAndExit() noreturn { - const argc = *argc_ptr; + const argc = argc_ptr.*; const argv = @ptrCast(&&u8, &argc_ptr[1]); const envp_nullable = @ptrCast(&?&u8, &argv[argc + 1]); var envp_count: usize = 0; @@ -56,7 +56,7 @@ fn posixCallMainAndExit() noreturn { const auxv = &@ptrCast(&usize, envp.ptr)[envp_count + 1]; var i: usize = 0; while (auxv[i] != 0) : (i += 2) { - if (auxv[i] < std.os.linux_aux_raw.len) std.os.linux_aux_raw[auxv[i]] = auxv[i+1]; + if (auxv[i] < std.os.linux_aux_raw.len) std.os.linux_aux_raw[auxv[i]] = auxv[i + 1]; } std.debug.assert(std.os.linux_aux_raw[std.elf.AT_PAGESZ] == std.os.page_size); } diff --git a/std/special/compiler_rt/fixuint.zig b/std/special/compiler_rt/fixuint.zig index b01bc48118e231aa2a98dd375c3dc45c113c6208..d9a7393fe4cd067504b10d8e2dc8f265d2c5168d 100644 --- a/std/special/compiler_rt/fixuint.zig +++ b/std/special/compiler_rt/fixuint.zig @@ -36,12 +36,10 @@ pub fn fixuint(comptime fp_t: type, comptime fixuint_t: type, a: fp_t) fixuint_t const significand: rep_t = (aAbs & significandMask) | implicitBit; // If either the value or the exponent is negative, the result is zero. - if (sign == -1 or exponent < 0) - return 0; + if (sign == -1 or exponent < 0) return 0; // If the value is too large for the integer type, saturate. - if (c_uint(exponent) >= fixuint_t.bit_count) - return ~fixuint_t(0); + if (c_uint(exponent) >= fixuint_t.bit_count) return ~fixuint_t(0); // If 0 <= exponent < significandBits, right shift to get the result. // Otherwise, shift left. diff --git a/std/special/compiler_rt/fixunsdfdi.zig b/std/special/compiler_rt/fixunsdfdi.zig index 37a8a01a50533b60da75ea6d2850d358fa4a57b8..1fa7ed758ebe3a4b9e3dbf70125901b325fdad2c 100644 --- a/std/special/compiler_rt/fixunsdfdi.zig +++ b/std/special/compiler_rt/fixunsdfdi.zig @@ -9,4 +9,3 @@ pub extern fn __fixunsdfdi(a: f64) u64 { test "import fixunsdfdi" { _ = @import("fixunsdfdi_test.zig"); } - diff --git a/std/special/compiler_rt/fixunsdfsi.zig b/std/special/compiler_rt/fixunsdfsi.zig index 0b5aebb7f6658d9c5f242495d4c68bf2326a94fc..a77cb8df896fa3566b5911c91d2dcf1499ae12a7 100644 --- a/std/special/compiler_rt/fixunsdfsi.zig +++ b/std/special/compiler_rt/fixunsdfsi.zig @@ -9,4 +9,3 @@ pub extern fn __fixunsdfsi(a: f64) u32 { test "import fixunsdfsi" { _ = @import("fixunsdfsi_test.zig"); } - diff --git a/std/special/compiler_rt/fixunssfti.zig b/std/special/compiler_rt/fixunssfti.zig index 0abd73fe76a08a54e4c9d9661e53593bdfa02c69..f0cd788d2e1a54a9f18c53e5d8d488e1392bc519 100644 --- a/std/special/compiler_rt/fixunssfti.zig +++ b/std/special/compiler_rt/fixunssfti.zig @@ -9,4 +9,3 @@ pub extern fn __fixunssfti(a: f32) u128 { test "import fixunssfti" { _ = @import("fixunssfti_test.zig"); } - diff --git a/std/special/compiler_rt/fixunstfti.zig b/std/special/compiler_rt/fixunstfti.zig index fea99eb6e83f69ab06f5dc2f97c4ca0bd78a4abf..cd6178164ab26eedbd1df45b9852af1eb4dc786d 100644 --- a/std/special/compiler_rt/fixunstfti.zig +++ b/std/special/compiler_rt/fixunstfti.zig @@ -9,4 +9,3 @@ pub extern fn __fixunstfti(a: f128) u128 { test "import fixunstfti" { _ = @import("fixunstfti_test.zig"); } - diff --git a/std/special/compiler_rt/index.zig b/std/special/compiler_rt/index.zig index 6ef43c4fed1eaf9ca2a2f55fb9c9f86a6c3edb07..44466a407de327a1389d2f89d762918745431b1b 100644 --- a/std/special/compiler_rt/index.zig +++ b/std/special/compiler_rt/index.zig @@ -91,9 +91,10 @@ pub fn setXmm0(comptime T: type, value: T) void { const aligned_value: T align(16) = value; asm volatile ( \\movaps (%[ptr]), %%xmm0 - : - : [ptr] "r" (&aligned_value) - : "xmm0"); + + : + : [ptr] "r" (&aligned_value) + : "xmm0"); } extern fn __udivdi3(a: u64, b: u64) u64 { @@ -282,26 +283,27 @@ extern fn __udivmodsi4(a: u32, b: u32, rem: &u32) u32 { @setRuntimeSafety(is_test); const d = __udivsi3(a, b); - *rem = u32(i32(a) -% (i32(d) * i32(b))); + rem.* = u32(i32(a) -% (i32(d) * i32(b))); return d; } - extern fn __udivsi3(n: u32, d: u32) u32 { @setRuntimeSafety(is_test); const n_uword_bits: c_uint = u32.bit_count; // special cases - if (d == 0) - return 0; // ?! - if (n == 0) - return 0; + if (d == 0) return 0; // ?! + if (n == 0) return 0; var sr = @bitCast(c_uint, c_int(@clz(d)) - c_int(@clz(n))); // 0 <= sr <= n_uword_bits - 1 or sr large - if (sr > n_uword_bits - 1) // d > r + if (sr > n_uword_bits - 1) { + // d > r return 0; - if (sr == n_uword_bits - 1) // d == 1 + } + if (sr == n_uword_bits - 1) { + // d == 1 return n; + } sr += 1; // 1 <= sr <= n_uword_bits - 1 // Not a special case @@ -340,139 +342,667 @@ fn test_one_umoddi3(a: u64, b: u64, expected_r: u64) void { } test "test_udivsi3" { - const cases = [][3]u32 { - []u32{0x00000000, 0x00000001, 0x00000000}, - []u32{0x00000000, 0x00000002, 0x00000000}, - []u32{0x00000000, 0x00000003, 0x00000000}, - []u32{0x00000000, 0x00000010, 0x00000000}, - []u32{0x00000000, 0x078644FA, 0x00000000}, - []u32{0x00000000, 0x0747AE14, 0x00000000}, - []u32{0x00000000, 0x7FFFFFFF, 0x00000000}, - []u32{0x00000000, 0x80000000, 0x00000000}, - []u32{0x00000000, 0xFFFFFFFD, 0x00000000}, - []u32{0x00000000, 0xFFFFFFFE, 0x00000000}, - []u32{0x00000000, 0xFFFFFFFF, 0x00000000}, - []u32{0x00000001, 0x00000001, 0x00000001}, - []u32{0x00000001, 0x00000002, 0x00000000}, - []u32{0x00000001, 0x00000003, 0x00000000}, - []u32{0x00000001, 0x00000010, 0x00000000}, - []u32{0x00000001, 0x078644FA, 0x00000000}, - []u32{0x00000001, 0x0747AE14, 0x00000000}, - []u32{0x00000001, 0x7FFFFFFF, 0x00000000}, - []u32{0x00000001, 0x80000000, 0x00000000}, - []u32{0x00000001, 0xFFFFFFFD, 0x00000000}, - []u32{0x00000001, 0xFFFFFFFE, 0x00000000}, - []u32{0x00000001, 0xFFFFFFFF, 0x00000000}, - []u32{0x00000002, 0x00000001, 0x00000002}, - []u32{0x00000002, 0x00000002, 0x00000001}, - []u32{0x00000002, 0x00000003, 0x00000000}, - []u32{0x00000002, 0x00000010, 0x00000000}, - []u32{0x00000002, 0x078644FA, 0x00000000}, - []u32{0x00000002, 0x0747AE14, 0x00000000}, - []u32{0x00000002, 0x7FFFFFFF, 0x00000000}, - []u32{0x00000002, 0x80000000, 0x00000000}, - []u32{0x00000002, 0xFFFFFFFD, 0x00000000}, - []u32{0x00000002, 0xFFFFFFFE, 0x00000000}, - []u32{0x00000002, 0xFFFFFFFF, 0x00000000}, - []u32{0x00000003, 0x00000001, 0x00000003}, - []u32{0x00000003, 0x00000002, 0x00000001}, - []u32{0x00000003, 0x00000003, 0x00000001}, - []u32{0x00000003, 0x00000010, 0x00000000}, - []u32{0x00000003, 0x078644FA, 0x00000000}, - []u32{0x00000003, 0x0747AE14, 0x00000000}, - []u32{0x00000003, 0x7FFFFFFF, 0x00000000}, - []u32{0x00000003, 0x80000000, 0x00000000}, - []u32{0x00000003, 0xFFFFFFFD, 0x00000000}, - []u32{0x00000003, 0xFFFFFFFE, 0x00000000}, - []u32{0x00000003, 0xFFFFFFFF, 0x00000000}, - []u32{0x00000010, 0x00000001, 0x00000010}, - []u32{0x00000010, 0x00000002, 0x00000008}, - []u32{0x00000010, 0x00000003, 0x00000005}, - []u32{0x00000010, 0x00000010, 0x00000001}, - []u32{0x00000010, 0x078644FA, 0x00000000}, - []u32{0x00000010, 0x0747AE14, 0x00000000}, - []u32{0x00000010, 0x7FFFFFFF, 0x00000000}, - []u32{0x00000010, 0x80000000, 0x00000000}, - []u32{0x00000010, 0xFFFFFFFD, 0x00000000}, - []u32{0x00000010, 0xFFFFFFFE, 0x00000000}, - []u32{0x00000010, 0xFFFFFFFF, 0x00000000}, - []u32{0x078644FA, 0x00000001, 0x078644FA}, - []u32{0x078644FA, 0x00000002, 0x03C3227D}, - []u32{0x078644FA, 0x00000003, 0x028216FE}, - []u32{0x078644FA, 0x00000010, 0x0078644F}, - []u32{0x078644FA, 0x078644FA, 0x00000001}, - []u32{0x078644FA, 0x0747AE14, 0x00000001}, - []u32{0x078644FA, 0x7FFFFFFF, 0x00000000}, - []u32{0x078644FA, 0x80000000, 0x00000000}, - []u32{0x078644FA, 0xFFFFFFFD, 0x00000000}, - []u32{0x078644FA, 0xFFFFFFFE, 0x00000000}, - []u32{0x078644FA, 0xFFFFFFFF, 0x00000000}, - []u32{0x0747AE14, 0x00000001, 0x0747AE14}, - []u32{0x0747AE14, 0x00000002, 0x03A3D70A}, - []u32{0x0747AE14, 0x00000003, 0x026D3A06}, - []u32{0x0747AE14, 0x00000010, 0x00747AE1}, - []u32{0x0747AE14, 0x078644FA, 0x00000000}, - []u32{0x0747AE14, 0x0747AE14, 0x00000001}, - []u32{0x0747AE14, 0x7FFFFFFF, 0x00000000}, - []u32{0x0747AE14, 0x80000000, 0x00000000}, - []u32{0x0747AE14, 0xFFFFFFFD, 0x00000000}, - []u32{0x0747AE14, 0xFFFFFFFE, 0x00000000}, - []u32{0x0747AE14, 0xFFFFFFFF, 0x00000000}, - []u32{0x7FFFFFFF, 0x00000001, 0x7FFFFFFF}, - []u32{0x7FFFFFFF, 0x00000002, 0x3FFFFFFF}, - []u32{0x7FFFFFFF, 0x00000003, 0x2AAAAAAA}, - []u32{0x7FFFFFFF, 0x00000010, 0x07FFFFFF}, - []u32{0x7FFFFFFF, 0x078644FA, 0x00000011}, - []u32{0x7FFFFFFF, 0x0747AE14, 0x00000011}, - []u32{0x7FFFFFFF, 0x7FFFFFFF, 0x00000001}, - []u32{0x7FFFFFFF, 0x80000000, 0x00000000}, - []u32{0x7FFFFFFF, 0xFFFFFFFD, 0x00000000}, - []u32{0x7FFFFFFF, 0xFFFFFFFE, 0x00000000}, - []u32{0x7FFFFFFF, 0xFFFFFFFF, 0x00000000}, - []u32{0x80000000, 0x00000001, 0x80000000}, - []u32{0x80000000, 0x00000002, 0x40000000}, - []u32{0x80000000, 0x00000003, 0x2AAAAAAA}, - []u32{0x80000000, 0x00000010, 0x08000000}, - []u32{0x80000000, 0x078644FA, 0x00000011}, - []u32{0x80000000, 0x0747AE14, 0x00000011}, - []u32{0x80000000, 0x7FFFFFFF, 0x00000001}, - []u32{0x80000000, 0x80000000, 0x00000001}, - []u32{0x80000000, 0xFFFFFFFD, 0x00000000}, - []u32{0x80000000, 0xFFFFFFFE, 0x00000000}, - []u32{0x80000000, 0xFFFFFFFF, 0x00000000}, - []u32{0xFFFFFFFD, 0x00000001, 0xFFFFFFFD}, - []u32{0xFFFFFFFD, 0x00000002, 0x7FFFFFFE}, - []u32{0xFFFFFFFD, 0x00000003, 0x55555554}, - []u32{0xFFFFFFFD, 0x00000010, 0x0FFFFFFF}, - []u32{0xFFFFFFFD, 0x078644FA, 0x00000022}, - []u32{0xFFFFFFFD, 0x0747AE14, 0x00000023}, - []u32{0xFFFFFFFD, 0x7FFFFFFF, 0x00000001}, - []u32{0xFFFFFFFD, 0x80000000, 0x00000001}, - []u32{0xFFFFFFFD, 0xFFFFFFFD, 0x00000001}, - []u32{0xFFFFFFFD, 0xFFFFFFFE, 0x00000000}, - []u32{0xFFFFFFFD, 0xFFFFFFFF, 0x00000000}, - []u32{0xFFFFFFFE, 0x00000001, 0xFFFFFFFE}, - []u32{0xFFFFFFFE, 0x00000002, 0x7FFFFFFF}, - []u32{0xFFFFFFFE, 0x00000003, 0x55555554}, - []u32{0xFFFFFFFE, 0x00000010, 0x0FFFFFFF}, - []u32{0xFFFFFFFE, 0x078644FA, 0x00000022}, - []u32{0xFFFFFFFE, 0x0747AE14, 0x00000023}, - []u32{0xFFFFFFFE, 0x7FFFFFFF, 0x00000002}, - []u32{0xFFFFFFFE, 0x80000000, 0x00000001}, - []u32{0xFFFFFFFE, 0xFFFFFFFD, 0x00000001}, - []u32{0xFFFFFFFE, 0xFFFFFFFE, 0x00000001}, - []u32{0xFFFFFFFE, 0xFFFFFFFF, 0x00000000}, - []u32{0xFFFFFFFF, 0x00000001, 0xFFFFFFFF}, - []u32{0xFFFFFFFF, 0x00000002, 0x7FFFFFFF}, - []u32{0xFFFFFFFF, 0x00000003, 0x55555555}, - []u32{0xFFFFFFFF, 0x00000010, 0x0FFFFFFF}, - []u32{0xFFFFFFFF, 0x078644FA, 0x00000022}, - []u32{0xFFFFFFFF, 0x0747AE14, 0x00000023}, - []u32{0xFFFFFFFF, 0x7FFFFFFF, 0x00000002}, - []u32{0xFFFFFFFF, 0x80000000, 0x00000001}, - []u32{0xFFFFFFFF, 0xFFFFFFFD, 0x00000001}, - []u32{0xFFFFFFFF, 0xFFFFFFFE, 0x00000001}, - []u32{0xFFFFFFFF, 0xFFFFFFFF, 0x00000001}, + const cases = [][3]u32{ + []u32{ + 0x00000000, + 0x00000001, + 0x00000000, + }, + []u32{ + 0x00000000, + 0x00000002, + 0x00000000, + }, + []u32{ + 0x00000000, + 0x00000003, + 0x00000000, + }, + []u32{ + 0x00000000, + 0x00000010, + 0x00000000, + }, + []u32{ + 0x00000000, + 0x078644FA, + 0x00000000, + }, + []u32{ + 0x00000000, + 0x0747AE14, + 0x00000000, + }, + []u32{ + 0x00000000, + 0x7FFFFFFF, + 0x00000000, + }, + []u32{ + 0x00000000, + 0x80000000, + 0x00000000, + }, + []u32{ + 0x00000000, + 0xFFFFFFFD, + 0x00000000, + }, + []u32{ + 0x00000000, + 0xFFFFFFFE, + 0x00000000, + }, + []u32{ + 0x00000000, + 0xFFFFFFFF, + 0x00000000, + }, + []u32{ + 0x00000001, + 0x00000001, + 0x00000001, + }, + []u32{ + 0x00000001, + 0x00000002, + 0x00000000, + }, + []u32{ + 0x00000001, + 0x00000003, + 0x00000000, + }, + []u32{ + 0x00000001, + 0x00000010, + 0x00000000, + }, + []u32{ + 0x00000001, + 0x078644FA, + 0x00000000, + }, + []u32{ + 0x00000001, + 0x0747AE14, + 0x00000000, + }, + []u32{ + 0x00000001, + 0x7FFFFFFF, + 0x00000000, + }, + []u32{ + 0x00000001, + 0x80000000, + 0x00000000, + }, + []u32{ + 0x00000001, + 0xFFFFFFFD, + 0x00000000, + }, + []u32{ + 0x00000001, + 0xFFFFFFFE, + 0x00000000, + }, + []u32{ + 0x00000001, + 0xFFFFFFFF, + 0x00000000, + }, + []u32{ + 0x00000002, + 0x00000001, + 0x00000002, + }, + []u32{ + 0x00000002, + 0x00000002, + 0x00000001, + }, + []u32{ + 0x00000002, + 0x00000003, + 0x00000000, + }, + []u32{ + 0x00000002, + 0x00000010, + 0x00000000, + }, + []u32{ + 0x00000002, + 0x078644FA, + 0x00000000, + }, + []u32{ + 0x00000002, + 0x0747AE14, + 0x00000000, + }, + []u32{ + 0x00000002, + 0x7FFFFFFF, + 0x00000000, + }, + []u32{ + 0x00000002, + 0x80000000, + 0x00000000, + }, + []u32{ + 0x00000002, + 0xFFFFFFFD, + 0x00000000, + }, + []u32{ + 0x00000002, + 0xFFFFFFFE, + 0x00000000, + }, + []u32{ + 0x00000002, + 0xFFFFFFFF, + 0x00000000, + }, + []u32{ + 0x00000003, + 0x00000001, + 0x00000003, + }, + []u32{ + 0x00000003, + 0x00000002, + 0x00000001, + }, + []u32{ + 0x00000003, + 0x00000003, + 0x00000001, + }, + []u32{ + 0x00000003, + 0x00000010, + 0x00000000, + }, + []u32{ + 0x00000003, + 0x078644FA, + 0x00000000, + }, + []u32{ + 0x00000003, + 0x0747AE14, + 0x00000000, + }, + []u32{ + 0x00000003, + 0x7FFFFFFF, + 0x00000000, + }, + []u32{ + 0x00000003, + 0x80000000, + 0x00000000, + }, + []u32{ + 0x00000003, + 0xFFFFFFFD, + 0x00000000, + }, + []u32{ + 0x00000003, + 0xFFFFFFFE, + 0x00000000, + }, + []u32{ + 0x00000003, + 0xFFFFFFFF, + 0x00000000, + }, + []u32{ + 0x00000010, + 0x00000001, + 0x00000010, + }, + []u32{ + 0x00000010, + 0x00000002, + 0x00000008, + }, + []u32{ + 0x00000010, + 0x00000003, + 0x00000005, + }, + []u32{ + 0x00000010, + 0x00000010, + 0x00000001, + }, + []u32{ + 0x00000010, + 0x078644FA, + 0x00000000, + }, + []u32{ + 0x00000010, + 0x0747AE14, + 0x00000000, + }, + []u32{ + 0x00000010, + 0x7FFFFFFF, + 0x00000000, + }, + []u32{ + 0x00000010, + 0x80000000, + 0x00000000, + }, + []u32{ + 0x00000010, + 0xFFFFFFFD, + 0x00000000, + }, + []u32{ + 0x00000010, + 0xFFFFFFFE, + 0x00000000, + }, + []u32{ + 0x00000010, + 0xFFFFFFFF, + 0x00000000, + }, + []u32{ + 0x078644FA, + 0x00000001, + 0x078644FA, + }, + []u32{ + 0x078644FA, + 0x00000002, + 0x03C3227D, + }, + []u32{ + 0x078644FA, + 0x00000003, + 0x028216FE, + }, + []u32{ + 0x078644FA, + 0x00000010, + 0x0078644F, + }, + []u32{ + 0x078644FA, + 0x078644FA, + 0x00000001, + }, + []u32{ + 0x078644FA, + 0x0747AE14, + 0x00000001, + }, + []u32{ + 0x078644FA, + 0x7FFFFFFF, + 0x00000000, + }, + []u32{ + 0x078644FA, + 0x80000000, + 0x00000000, + }, + []u32{ + 0x078644FA, + 0xFFFFFFFD, + 0x00000000, + }, + []u32{ + 0x078644FA, + 0xFFFFFFFE, + 0x00000000, + }, + []u32{ + 0x078644FA, + 0xFFFFFFFF, + 0x00000000, + }, + []u32{ + 0x0747AE14, + 0x00000001, + 0x0747AE14, + }, + []u32{ + 0x0747AE14, + 0x00000002, + 0x03A3D70A, + }, + []u32{ + 0x0747AE14, + 0x00000003, + 0x026D3A06, + }, + []u32{ + 0x0747AE14, + 0x00000010, + 0x00747AE1, + }, + []u32{ + 0x0747AE14, + 0x078644FA, + 0x00000000, + }, + []u32{ + 0x0747AE14, + 0x0747AE14, + 0x00000001, + }, + []u32{ + 0x0747AE14, + 0x7FFFFFFF, + 0x00000000, + }, + []u32{ + 0x0747AE14, + 0x80000000, + 0x00000000, + }, + []u32{ + 0x0747AE14, + 0xFFFFFFFD, + 0x00000000, + }, + []u32{ + 0x0747AE14, + 0xFFFFFFFE, + 0x00000000, + }, + []u32{ + 0x0747AE14, + 0xFFFFFFFF, + 0x00000000, + }, + []u32{ + 0x7FFFFFFF, + 0x00000001, + 0x7FFFFFFF, + }, + []u32{ + 0x7FFFFFFF, + 0x00000002, + 0x3FFFFFFF, + }, + []u32{ + 0x7FFFFFFF, + 0x00000003, + 0x2AAAAAAA, + }, + []u32{ + 0x7FFFFFFF, + 0x00000010, + 0x07FFFFFF, + }, + []u32{ + 0x7FFFFFFF, + 0x078644FA, + 0x00000011, + }, + []u32{ + 0x7FFFFFFF, + 0x0747AE14, + 0x00000011, + }, + []u32{ + 0x7FFFFFFF, + 0x7FFFFFFF, + 0x00000001, + }, + []u32{ + 0x7FFFFFFF, + 0x80000000, + 0x00000000, + }, + []u32{ + 0x7FFFFFFF, + 0xFFFFFFFD, + 0x00000000, + }, + []u32{ + 0x7FFFFFFF, + 0xFFFFFFFE, + 0x00000000, + }, + []u32{ + 0x7FFFFFFF, + 0xFFFFFFFF, + 0x00000000, + }, + []u32{ + 0x80000000, + 0x00000001, + 0x80000000, + }, + []u32{ + 0x80000000, + 0x00000002, + 0x40000000, + }, + []u32{ + 0x80000000, + 0x00000003, + 0x2AAAAAAA, + }, + []u32{ + 0x80000000, + 0x00000010, + 0x08000000, + }, + []u32{ + 0x80000000, + 0x078644FA, + 0x00000011, + }, + []u32{ + 0x80000000, + 0x0747AE14, + 0x00000011, + }, + []u32{ + 0x80000000, + 0x7FFFFFFF, + 0x00000001, + }, + []u32{ + 0x80000000, + 0x80000000, + 0x00000001, + }, + []u32{ + 0x80000000, + 0xFFFFFFFD, + 0x00000000, + }, + []u32{ + 0x80000000, + 0xFFFFFFFE, + 0x00000000, + }, + []u32{ + 0x80000000, + 0xFFFFFFFF, + 0x00000000, + }, + []u32{ + 0xFFFFFFFD, + 0x00000001, + 0xFFFFFFFD, + }, + []u32{ + 0xFFFFFFFD, + 0x00000002, + 0x7FFFFFFE, + }, + []u32{ + 0xFFFFFFFD, + 0x00000003, + 0x55555554, + }, + []u32{ + 0xFFFFFFFD, + 0x00000010, + 0x0FFFFFFF, + }, + []u32{ + 0xFFFFFFFD, + 0x078644FA, + 0x00000022, + }, + []u32{ + 0xFFFFFFFD, + 0x0747AE14, + 0x00000023, + }, + []u32{ + 0xFFFFFFFD, + 0x7FFFFFFF, + 0x00000001, + }, + []u32{ + 0xFFFFFFFD, + 0x80000000, + 0x00000001, + }, + []u32{ + 0xFFFFFFFD, + 0xFFFFFFFD, + 0x00000001, + }, + []u32{ + 0xFFFFFFFD, + 0xFFFFFFFE, + 0x00000000, + }, + []u32{ + 0xFFFFFFFD, + 0xFFFFFFFF, + 0x00000000, + }, + []u32{ + 0xFFFFFFFE, + 0x00000001, + 0xFFFFFFFE, + }, + []u32{ + 0xFFFFFFFE, + 0x00000002, + 0x7FFFFFFF, + }, + []u32{ + 0xFFFFFFFE, + 0x00000003, + 0x55555554, + }, + []u32{ + 0xFFFFFFFE, + 0x00000010, + 0x0FFFFFFF, + }, + []u32{ + 0xFFFFFFFE, + 0x078644FA, + 0x00000022, + }, + []u32{ + 0xFFFFFFFE, + 0x0747AE14, + 0x00000023, + }, + []u32{ + 0xFFFFFFFE, + 0x7FFFFFFF, + 0x00000002, + }, + []u32{ + 0xFFFFFFFE, + 0x80000000, + 0x00000001, + }, + []u32{ + 0xFFFFFFFE, + 0xFFFFFFFD, + 0x00000001, + }, + []u32{ + 0xFFFFFFFE, + 0xFFFFFFFE, + 0x00000001, + }, + []u32{ + 0xFFFFFFFE, + 0xFFFFFFFF, + 0x00000000, + }, + []u32{ + 0xFFFFFFFF, + 0x00000001, + 0xFFFFFFFF, + }, + []u32{ + 0xFFFFFFFF, + 0x00000002, + 0x7FFFFFFF, + }, + []u32{ + 0xFFFFFFFF, + 0x00000003, + 0x55555555, + }, + []u32{ + 0xFFFFFFFF, + 0x00000010, + 0x0FFFFFFF, + }, + []u32{ + 0xFFFFFFFF, + 0x078644FA, + 0x00000022, + }, + []u32{ + 0xFFFFFFFF, + 0x0747AE14, + 0x00000023, + }, + []u32{ + 0xFFFFFFFF, + 0x7FFFFFFF, + 0x00000002, + }, + []u32{ + 0xFFFFFFFF, + 0x80000000, + 0x00000001, + }, + []u32{ + 0xFFFFFFFF, + 0xFFFFFFFD, + 0x00000001, + }, + []u32{ + 0xFFFFFFFF, + 0xFFFFFFFE, + 0x00000001, + }, + []u32{ + 0xFFFFFFFF, + 0xFFFFFFFF, + 0x00000001, + }, }; for (cases) |case| { diff --git a/std/special/compiler_rt/udivmod.zig b/std/special/compiler_rt/udivmod.zig index 07eaef583ca815f64b56323d451972f570f89aa3..e8a86c5c44cf2468d2fbc2409b3505b611ced643 100644 --- a/std/special/compiler_rt/udivmod.zig +++ b/std/special/compiler_rt/udivmod.zig @@ -1,7 +1,10 @@ const builtin = @import("builtin"); const is_test = builtin.is_test; -const low = switch (builtin.endian) { builtin.Endian.Big => 1, builtin.Endian.Little => 0 }; +const low = switch (builtin.endian) { + builtin.Endian.Big => 1, + builtin.Endian.Little => 0, +}; const high = 1 - low; pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem: ?&DoubleInt) DoubleInt { @@ -11,8 +14,8 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem: const SignedDoubleInt = @IntType(true, DoubleInt.bit_count); const Log2SingleInt = @import("../../math/index.zig").Log2Int(SingleInt); - const n = *@ptrCast(&const [2]SingleInt, &a); // TODO issue #421 - const d = *@ptrCast(&const [2]SingleInt, &b); // TODO issue #421 + const n = @ptrCast(&const [2]SingleInt, &a).*; // TODO issue #421 + const d = @ptrCast(&const [2]SingleInt, &b).*; // TODO issue #421 var q: [2]SingleInt = undefined; var r: [2]SingleInt = undefined; var sr: c_uint = undefined; @@ -23,7 +26,7 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem: // --- // 0 X if (maybe_rem) |rem| { - *rem = n[low] % d[low]; + rem.* = n[low] % d[low]; } return n[low] / d[low]; } @@ -31,7 +34,7 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem: // --- // K X if (maybe_rem) |rem| { - *rem = n[low]; + rem.* = n[low]; } return 0; } @@ -42,7 +45,7 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem: // --- // 0 0 if (maybe_rem) |rem| { - *rem = n[high] % d[low]; + rem.* = n[high] % d[low]; } return n[high] / d[low]; } @@ -54,7 +57,7 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem: if (maybe_rem) |rem| { r[high] = n[high] % d[high]; r[low] = 0; - *rem = *@ptrCast(&align(@alignOf(SingleInt)) DoubleInt, &r[0]); // TODO issue #421 + rem.* = @ptrCast(&align(@alignOf(SingleInt)) DoubleInt, &r[0]).*; // TODO issue #421 } return n[high] / d[high]; } @@ -66,7 +69,7 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem: if (maybe_rem) |rem| { r[low] = n[low]; r[high] = n[high] & (d[high] - 1); - *rem = *@ptrCast(&align(@alignOf(SingleInt)) DoubleInt, &r[0]); // TODO issue #421 + rem.* = @ptrCast(&align(@alignOf(SingleInt)) DoubleInt, &r[0]).*; // TODO issue #421 } return n[high] >> Log2SingleInt(@ctz(d[high])); } @@ -77,7 +80,7 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem: // 0 <= sr <= SingleInt.bit_count - 2 or sr large if (sr > SingleInt.bit_count - 2) { if (maybe_rem) |rem| { - *rem = a; + rem.* = a; } return 0; } @@ -98,7 +101,7 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem: if ((d[low] & (d[low] - 1)) == 0) { // d is a power of 2 if (maybe_rem) |rem| { - *rem = n[low] & (d[low] - 1); + rem.* = n[low] & (d[low] - 1); } if (d[low] == 1) { return a; @@ -106,7 +109,7 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem: sr = @ctz(d[low]); q[high] = n[high] >> Log2SingleInt(sr); q[low] = (n[high] << Log2SingleInt(SingleInt.bit_count - sr)) | (n[low] >> Log2SingleInt(sr)); - return *@ptrCast(&align(@alignOf(SingleInt)) DoubleInt, &q[0]); // TODO issue #421 + return @ptrCast(&align(@alignOf(SingleInt)) DoubleInt, &q[0]).*; // TODO issue #421 } // K X // --- @@ -141,7 +144,7 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem: // 0 <= sr <= SingleInt.bit_count - 1 or sr large if (sr > SingleInt.bit_count - 1) { if (maybe_rem) |rem| { - *rem = a; + rem.* = a; } return 0; } @@ -170,25 +173,25 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem: var r_all: DoubleInt = undefined; while (sr > 0) : (sr -= 1) { // r:q = ((r:q) << 1) | carry - r[high] = (r[high] << 1) | (r[low] >> (SingleInt.bit_count - 1)); - r[low] = (r[low] << 1) | (q[high] >> (SingleInt.bit_count - 1)); - q[high] = (q[high] << 1) | (q[low] >> (SingleInt.bit_count - 1)); - q[low] = (q[low] << 1) | carry; + r[high] = (r[high] << 1) | (r[low] >> (SingleInt.bit_count - 1)); + r[low] = (r[low] << 1) | (q[high] >> (SingleInt.bit_count - 1)); + q[high] = (q[high] << 1) | (q[low] >> (SingleInt.bit_count - 1)); + q[low] = (q[low] << 1) | carry; // carry = 0; // if (r.all >= b) // { // r.all -= b; // carry = 1; // } - r_all = *@ptrCast(&align(@alignOf(SingleInt)) DoubleInt, &r[0]); // TODO issue #421 + r_all = @ptrCast(&align(@alignOf(SingleInt)) DoubleInt, &r[0]).*; // TODO issue #421 const s: SignedDoubleInt = SignedDoubleInt(b -% r_all -% 1) >> (DoubleInt.bit_count - 1); carry = u32(s & 1); r_all -= b & @bitCast(DoubleInt, s); - r = *@ptrCast(&[2]SingleInt, &r_all); // TODO issue #421 + r = @ptrCast(&[2]SingleInt, &r_all).*; // TODO issue #421 } - const q_all = ((*@ptrCast(&align(@alignOf(SingleInt)) DoubleInt, &q[0])) << 1) | carry; // TODO issue #421 + const q_all = ((@ptrCast(&align(@alignOf(SingleInt)) DoubleInt, &q[0]).*) << 1) | carry; // TODO issue #421 if (maybe_rem) |rem| { - *rem = r_all; + rem.* = r_all; } return q_all; } diff --git a/std/special/compiler_rt/udivmodti4.zig b/std/special/compiler_rt/udivmodti4.zig index f8fdebe4dbdf54096430eeaaba12561cd17f8500..816f82b9003464e3eee30fce11a76f33e0d12313 100644 --- a/std/special/compiler_rt/udivmodti4.zig +++ b/std/special/compiler_rt/udivmodti4.zig @@ -9,7 +9,7 @@ pub extern fn __udivmodti4(a: u128, b: u128, maybe_rem: ?&u128) u128 { pub extern fn __udivmodti4_windows_x86_64(a: &const u128, b: &const u128, maybe_rem: ?&u128) void { @setRuntimeSafety(builtin.is_test); - compiler_rt.setXmm0(u128, udivmod(u128, *a, *b, maybe_rem)); + compiler_rt.setXmm0(u128, udivmod(u128, a.*, b.*, maybe_rem)); } test "import udivmodti4" { diff --git a/std/special/compiler_rt/umodti3.zig b/std/special/compiler_rt/umodti3.zig index 3e8b80058e46c53e7ffb1addedf110bd96ab98ab..11e2955bb346f55161cb2129bfdb84220036b4d9 100644 --- a/std/special/compiler_rt/umodti3.zig +++ b/std/special/compiler_rt/umodti3.zig @@ -11,5 +11,5 @@ pub extern fn __umodti3(a: u128, b: u128) u128 { pub extern fn __umodti3_windows_x86_64(a: &const u128, b: &const u128) void { @setRuntimeSafety(builtin.is_test); - compiler_rt.setXmm0(u128, __umodti3(*a, *b)); + compiler_rt.setXmm0(u128, __umodti3(a.*, b.*)); } diff --git a/test/cases/cast.zig b/test/cases/cast.zig index 547cca5797f3a5100b757cbbee91297355ffd080..8b6afb4310497f1450872dc5155895144051e237 100644 --- a/test/cases/cast.zig +++ b/test/cases/cast.zig @@ -14,7 +14,7 @@ test "integer literal to pointer cast" { } test "pointer reinterpret const float to int" { - const float: f64 = 5.99999999999994648725e - 01; + const float: f64 = 5.99999999999994648725e-01; const float_ptr = &float; const int_ptr = @ptrCast(&const i32, float_ptr); const int_val = int_ptr.*; @@ -121,13 +121,13 @@ test "implicitly cast indirect pointer to maybe-indirect pointer" { return (p.*).x; } fn maybeConstConst(p: ?&const &const Self) u8 { - return (??p.*).x; + return ((??p).*).x; } fn constConstConst(p: &const &const &const Self) u8 { return (p.*.*).x; } fn maybeConstConstConst(p: ?&const &const &const Self) u8 { - return (??p.*.*).x; + return ((??p).*.*).x; } }; const s = S { diff --git a/test/cases/generics.zig b/test/cases/generics.zig index da8a7dcad6c230628c631af250677e8b3b17c76a..3fb33d0495e5cbb54a0170c36be5f1909c667071 100644 --- a/test/cases/generics.zig +++ b/test/cases/generics.zig @@ -127,7 +127,7 @@ test "generic fn with implicit cast" { }) == 0); } fn getByte(ptr: ?&const u8) u8 { - return ??ptr.*; + return (??ptr).*; } fn getFirstByte(comptime T: type, mem: []const T) u8 { return getByte(@ptrCast(&const u8, &mem[0])); -- 2.54.0 From 4787127cf6418f7a819c9d6f07a9046d76e0de65 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 10 May 2018 00:29:49 -0400 Subject: [PATCH 04/47] partial conversion to post-fix pointer deref using zig fmt --- std/atomic/queue.zig | 12 +- std/atomic/stack.zig | 16 +- std/buffer.zig | 11 +- std/build.zig | 207 +++++------- std/crypto/blake2.zig | 709 ++++++++++++++++++++++++++------------- std/crypto/hmac.zig | 4 +- std/crypto/sha3.zig | 287 ++++++++++------ std/event.zig | 53 ++- std/hash/crc.zig | 32 +- std/hash_map.zig | 94 +++--- std/json.zig | 207 +++++++----- std/math/acos.zig | 14 +- std/math/asin.zig | 18 +- std/math/atan2.zig | 66 ++-- std/math/cbrt.zig | 10 +- std/math/ceil.zig | 4 +- std/math/cos.zig | 12 +- std/math/floor.zig | 4 +- std/math/fma.zig | 7 +- std/math/hypot.zig | 8 +- std/math/ln.zig | 6 +- std/math/log10.zig | 18 +- std/math/log2.zig | 7 +- std/math/round.zig | 8 +- std/math/sin.zig | 12 +- std/math/tan.zig | 6 +- std/net.zig | 40 +-- std/os/child_process.zig | 192 ++++++----- std/segmented_list.zig | 54 +-- std/sort.zig | 562 ++++++++++++++++++++++--------- 30 files changed, 1618 insertions(+), 1062 deletions(-) diff --git a/std/atomic/queue.zig b/std/atomic/queue.zig index e25c8e6b17021352999c5511b8b0578b94fe5a12..288a2b3b48e8e3e8ce3af56a46bc79277f3dfa8c 100644 --- a/std/atomic/queue.zig +++ b/std/atomic/queue.zig @@ -70,7 +70,7 @@ test "std.atomic.queue" { var queue: Queue(i32) = undefined; queue.init(); - var context = Context { + var context = Context{ .allocator = a, .queue = &queue, .put_sum = 0, @@ -81,16 +81,18 @@ test "std.atomic.queue" { var putters: [put_thread_count]&std.os.Thread = undefined; for (putters) |*t| { - *t = try std.os.spawnThread(&context, startPuts); + t.* = try std.os.spawnThread(&context, startPuts); } var getters: [put_thread_count]&std.os.Thread = undefined; for (getters) |*t| { - *t = try std.os.spawnThread(&context, startGets); + t.* = try std.os.spawnThread(&context, startGets); } - for (putters) |t| t.wait(); + for (putters) |t| + t.wait(); _ = @atomicRmw(u8, &context.puts_done, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst); - for (getters) |t| t.wait(); + for (getters) |t| + t.wait(); std.debug.assert(context.put_sum == context.get_sum); std.debug.assert(context.get_count == puts_per_thread * put_thread_count); diff --git a/std/atomic/stack.zig b/std/atomic/stack.zig index 4a3dbef32b76ddffcc3a18b8004b76bf236d28e3..400a1a3c4ff7c753b0ca02f67524017b4d1889c6 100644 --- a/std/atomic/stack.zig +++ b/std/atomic/stack.zig @@ -14,9 +14,7 @@ pub fn Stack(comptime T: type) type { }; pub fn init() Self { - return Self { - .root = null, - }; + return Self{ .root = null }; } /// push operation, but only if you are the first item in the stack. if you did not succeed in @@ -75,7 +73,7 @@ test "std.atomic.stack" { var a = &fixed_buffer_allocator.allocator; var stack = Stack(i32).init(); - var context = Context { + var context = Context{ .allocator = a, .stack = &stack, .put_sum = 0, @@ -86,16 +84,18 @@ test "std.atomic.stack" { var putters: [put_thread_count]&std.os.Thread = undefined; for (putters) |*t| { - *t = try std.os.spawnThread(&context, startPuts); + t.* = try std.os.spawnThread(&context, startPuts); } var getters: [put_thread_count]&std.os.Thread = undefined; for (getters) |*t| { - *t = try std.os.spawnThread(&context, startGets); + t.* = try std.os.spawnThread(&context, startGets); } - for (putters) |t| t.wait(); + for (putters) |t| + t.wait(); _ = @atomicRmw(u8, &context.puts_done, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst); - for (getters) |t| t.wait(); + for (getters) |t| + t.wait(); std.debug.assert(context.put_sum == context.get_sum); std.debug.assert(context.get_count == puts_per_thread * put_thread_count); diff --git a/std/buffer.zig b/std/buffer.zig index 041d891dec374a8ddd1e7b85edc25d07f8af75d5..cf530c3c9e26d87d7a18349174ad71d15017ff97 100644 --- a/std/buffer.zig +++ b/std/buffer.zig @@ -31,9 +31,7 @@ pub const Buffer = struct { /// * ::replaceContentsBuffer /// * ::resize pub fn initNull(allocator: &Allocator) Buffer { - return Buffer { - .list = ArrayList(u8).init(allocator), - }; + return Buffer{ .list = ArrayList(u8).init(allocator) }; } /// Must deinitialize with deinit. @@ -45,9 +43,7 @@ pub const Buffer = struct { /// allocated with `allocator`. /// Must deinitialize with deinit. pub fn fromOwnedSlice(allocator: &Allocator, slice: []u8) Buffer { - var self = Buffer { - .list = ArrayList(u8).fromOwnedSlice(allocator, slice), - }; + var self = Buffer{ .list = ArrayList(u8).fromOwnedSlice(allocator, slice) }; self.list.append(0); return self; } @@ -57,11 +53,10 @@ pub const Buffer = struct { pub fn toOwnedSlice(self: &Buffer) []u8 { const allocator = self.list.allocator; const result = allocator.shrink(u8, self.list.items, self.len()); - *self = initNull(allocator); + self.* = initNull(allocator); return result; } - pub fn deinit(self: &Buffer) void { self.list.deinit(); } diff --git a/std/build.zig b/std/build.zig index a312b28a6f38a1b59b87799bb79ad01b1658c936..276176c63c5ae8b05135ddd9842e6be3951e4ab6 100644 --- a/std/build.zig +++ b/std/build.zig @@ -82,10 +82,8 @@ pub const Builder = struct { description: []const u8, }; - pub fn init(allocator: &Allocator, zig_exe: []const u8, build_root: []const u8, - cache_root: []const u8) Builder - { - var self = Builder { + pub fn init(allocator: &Allocator, zig_exe: []const u8, build_root: []const u8, cache_root: []const u8) Builder { + var self = Builder{ .zig_exe = zig_exe, .build_root = build_root, .cache_root = os.path.relative(allocator, build_root, cache_root) catch unreachable, @@ -112,12 +110,12 @@ pub const Builder = struct { .lib_dir = undefined, .exe_dir = undefined, .installed_files = ArrayList([]const u8).init(allocator), - .uninstall_tls = TopLevelStep { + .uninstall_tls = TopLevelStep{ .step = Step.init("uninstall", allocator, makeUninstall), .description = "Remove build artifacts from prefix path", }, .have_uninstall_step = false, - .install_tls = TopLevelStep { + .install_tls = TopLevelStep{ .step = Step.initNoOp("install", allocator), .description = "Copy build artifacts to prefix path", }, @@ -151,9 +149,7 @@ pub const Builder = struct { return LibExeObjStep.createObject(self, name, root_src); } - pub fn addSharedLibrary(self: &Builder, name: []const u8, root_src: ?[]const u8, - ver: &const Version) &LibExeObjStep - { + pub fn addSharedLibrary(self: &Builder, name: []const u8, root_src: ?[]const u8, ver: &const Version) &LibExeObjStep { return LibExeObjStep.createSharedLibrary(self, name, root_src, ver); } @@ -163,7 +159,7 @@ pub const Builder = struct { pub fn addTest(self: &Builder, root_src: []const u8) &TestStep { const test_step = self.allocator.create(TestStep) catch unreachable; - *test_step = TestStep.init(self, root_src); + test_step.* = TestStep.init(self, root_src); return test_step; } @@ -190,33 +186,31 @@ pub const Builder = struct { } /// ::argv is copied. - pub fn addCommand(self: &Builder, cwd: ?[]const u8, env_map: &const BufMap, - argv: []const []const u8) &CommandStep - { + pub fn addCommand(self: &Builder, cwd: ?[]const u8, env_map: &const BufMap, argv: []const []const u8) &CommandStep { return CommandStep.create(self, cwd, env_map, argv); } pub fn addWriteFile(self: &Builder, file_path: []const u8, data: []const u8) &WriteFileStep { const write_file_step = self.allocator.create(WriteFileStep) catch unreachable; - *write_file_step = WriteFileStep.init(self, file_path, data); + write_file_step.* = WriteFileStep.init(self, file_path, data); return write_file_step; } pub fn addLog(self: &Builder, comptime format: []const u8, args: ...) &LogStep { const data = self.fmt(format, args); const log_step = self.allocator.create(LogStep) catch unreachable; - *log_step = LogStep.init(self, data); + log_step.* = LogStep.init(self, data); return log_step; } pub fn addRemoveDirTree(self: &Builder, dir_path: []const u8) &RemoveDirStep { const remove_dir_step = self.allocator.create(RemoveDirStep) catch unreachable; - *remove_dir_step = RemoveDirStep.init(self, dir_path); + remove_dir_step.* = RemoveDirStep.init(self, dir_path); return remove_dir_step; } pub fn version(self: &const Builder, major: u32, minor: u32, patch: u32) Version { - return Version { + return Version{ .major = major, .minor = minor, .patch = patch, @@ -254,8 +248,7 @@ pub const Builder = struct { } pub fn getInstallStep(self: &Builder) &Step { - if (self.have_install_step) - return &self.install_tls.step; + if (self.have_install_step) return &self.install_tls.step; self.top_level_steps.append(&self.install_tls) catch unreachable; self.have_install_step = true; @@ -263,8 +256,7 @@ pub const Builder = struct { } pub fn getUninstallStep(self: &Builder) &Step { - if (self.have_uninstall_step) - return &self.uninstall_tls.step; + if (self.have_uninstall_step) return &self.uninstall_tls.step; self.top_level_steps.append(&self.uninstall_tls) catch unreachable; self.have_uninstall_step = true; @@ -360,7 +352,7 @@ pub const Builder = struct { pub fn option(self: &Builder, comptime T: type, name: []const u8, description: []const u8) ?T { const type_id = comptime typeToEnum(T); - const available_option = AvailableOption { + const available_option = AvailableOption{ .name = name, .type_id = type_id, .description = description, @@ -413,7 +405,7 @@ pub const Builder = struct { pub fn step(self: &Builder, name: []const u8, description: []const u8) &Step { const step_info = self.allocator.create(TopLevelStep) catch unreachable; - *step_info = TopLevelStep { + step_info.* = TopLevelStep{ .step = Step.initNoOp(name, self.allocator), .description = description, }; @@ -446,9 +438,9 @@ pub const Builder = struct { } pub fn addUserInputOption(self: &Builder, name: []const u8, value: []const u8) bool { - if (self.user_input_options.put(name, UserInputOption { + if (self.user_input_options.put(name, UserInputOption{ .name = name, - .value = UserValue { .Scalar = value }, + .value = UserValue{ .Scalar = value }, .used = false, }) catch unreachable) |*prev_value| { // option already exists @@ -458,18 +450,18 @@ pub const Builder = struct { var list = ArrayList([]const u8).init(self.allocator); list.append(s) catch unreachable; list.append(value) catch unreachable; - _ = self.user_input_options.put(name, UserInputOption { + _ = self.user_input_options.put(name, UserInputOption{ .name = name, - .value = UserValue { .List = list }, + .value = UserValue{ .List = list }, .used = false, }) catch unreachable; }, UserValue.List => |*list| { // append to the list list.append(value) catch unreachable; - _ = self.user_input_options.put(name, UserInputOption { + _ = self.user_input_options.put(name, UserInputOption{ .name = name, - .value = UserValue { .List = *list }, + .value = UserValue{ .List = list.* }, .used = false, }) catch unreachable; }, @@ -483,9 +475,9 @@ pub const Builder = struct { } pub fn addUserInputFlag(self: &Builder, name: []const u8) bool { - if (self.user_input_options.put(name, UserInputOption { + if (self.user_input_options.put(name, UserInputOption{ .name = name, - .value = UserValue {.Flag = {} }, + .value = UserValue{ .Flag = {} }, .used = false, }) catch unreachable) |*prev_value| { switch (prev_value.value) { @@ -556,9 +548,7 @@ pub const Builder = struct { warn("\n"); } - fn spawnChildEnvMap(self: &Builder, cwd: ?[]const u8, env_map: &const BufMap, - argv: []const []const u8) !void - { + fn spawnChildEnvMap(self: &Builder, cwd: ?[]const u8, env_map: &const BufMap, argv: []const []const u8) !void { if (self.verbose) { printCmd(cwd, argv); } @@ -617,7 +607,7 @@ pub const Builder = struct { self.pushInstalledFile(full_dest_path); const install_step = self.allocator.create(InstallFileStep) catch unreachable; - *install_step = InstallFileStep.init(self, src_path, full_dest_path); + install_step.* = InstallFileStep.init(self, src_path, full_dest_path); return install_step; } @@ -659,25 +649,23 @@ pub const Builder = struct { if (builtin.environ == builtin.Environ.msvc) { return "cl.exe"; } else { - return os.getEnvVarOwned(self.allocator, "CC") catch |err| + return os.getEnvVarOwned(self.allocator, "CC") catch |err| if (err == error.EnvironmentVariableNotFound) ([]const u8)("cc") else - debug.panic("Unable to get environment variable: {}", err) - ; + debug.panic("Unable to get environment variable: {}", err); } } pub fn findProgram(self: &Builder, names: []const []const u8, paths: []const []const u8) ![]const u8 { // TODO report error for ambiguous situations - const exe_extension = (Target { .Native = {}}).exeFileExt(); + const exe_extension = (Target{ .Native = {} }).exeFileExt(); for (self.search_prefixes.toSliceConst()) |search_prefix| { for (names) |name| { if (os.path.isAbsolute(name)) { return name; } - const full_path = try os.path.join(self.allocator, search_prefix, "bin", - self.fmt("{}{}", name, exe_extension)); + const full_path = try os.path.join(self.allocator, search_prefix, "bin", self.fmt("{}{}", name, exe_extension)); if (os.path.real(self.allocator, full_path)) |real_path| { return real_path; } else |_| { @@ -761,7 +749,7 @@ pub const Target = union(enum) { Cross: CrossTarget, pub fn oFileExt(self: &const Target) []const u8 { - const environ = switch (*self) { + const environ = switch (self.*) { Target.Native => builtin.environ, Target.Cross => |t| t.environ, }; @@ -786,7 +774,7 @@ pub const Target = union(enum) { } pub fn getOs(self: &const Target) builtin.Os { - return switch (*self) { + return switch (self.*) { Target.Native => builtin.os, Target.Cross => |t| t.os, }; @@ -794,7 +782,8 @@ pub const Target = union(enum) { pub fn isDarwin(self: &const Target) bool { return switch (self.getOs()) { - builtin.Os.ios, builtin.Os.macosx => true, + builtin.Os.ios, + builtin.Os.macosx => true, else => false, }; } @@ -860,61 +849,57 @@ pub const LibExeObjStep = struct { Obj, }; - pub fn createSharedLibrary(builder: &Builder, name: []const u8, root_src: ?[]const u8, - ver: &const Version) &LibExeObjStep - { + pub fn createSharedLibrary(builder: &Builder, name: []const u8, root_src: ?[]const u8, ver: &const Version) &LibExeObjStep { const self = builder.allocator.create(LibExeObjStep) catch unreachable; - *self = initExtraArgs(builder, name, root_src, Kind.Lib, false, ver); + self.* = initExtraArgs(builder, name, root_src, Kind.Lib, false, ver); return self; } pub fn createCSharedLibrary(builder: &Builder, name: []const u8, version: &const Version) &LibExeObjStep { const self = builder.allocator.create(LibExeObjStep) catch unreachable; - *self = initC(builder, name, Kind.Lib, version, false); + self.* = initC(builder, name, Kind.Lib, version, false); return self; } pub fn createStaticLibrary(builder: &Builder, name: []const u8, root_src: ?[]const u8) &LibExeObjStep { const self = builder.allocator.create(LibExeObjStep) catch unreachable; - *self = initExtraArgs(builder, name, root_src, Kind.Lib, true, builder.version(0, 0, 0)); + self.* = initExtraArgs(builder, name, root_src, Kind.Lib, true, builder.version(0, 0, 0)); return self; } pub fn createCStaticLibrary(builder: &Builder, name: []const u8) &LibExeObjStep { const self = builder.allocator.create(LibExeObjStep) catch unreachable; - *self = initC(builder, name, Kind.Lib, builder.version(0, 0, 0), true); + self.* = initC(builder, name, Kind.Lib, builder.version(0, 0, 0), true); return self; } pub fn createObject(builder: &Builder, name: []const u8, root_src: []const u8) &LibExeObjStep { const self = builder.allocator.create(LibExeObjStep) catch unreachable; - *self = initExtraArgs(builder, name, root_src, Kind.Obj, false, builder.version(0, 0, 0)); + self.* = initExtraArgs(builder, name, root_src, Kind.Obj, false, builder.version(0, 0, 0)); return self; } pub fn createCObject(builder: &Builder, name: []const u8, src: []const u8) &LibExeObjStep { const self = builder.allocator.create(LibExeObjStep) catch unreachable; - *self = initC(builder, name, Kind.Obj, builder.version(0, 0, 0), false); + self.* = initC(builder, name, Kind.Obj, builder.version(0, 0, 0), false); self.object_src = src; return self; } pub fn createExecutable(builder: &Builder, name: []const u8, root_src: ?[]const u8) &LibExeObjStep { const self = builder.allocator.create(LibExeObjStep) catch unreachable; - *self = initExtraArgs(builder, name, root_src, Kind.Exe, false, builder.version(0, 0, 0)); + self.* = initExtraArgs(builder, name, root_src, Kind.Exe, false, builder.version(0, 0, 0)); return self; } pub fn createCExecutable(builder: &Builder, name: []const u8) &LibExeObjStep { const self = builder.allocator.create(LibExeObjStep) catch unreachable; - *self = initC(builder, name, Kind.Exe, builder.version(0, 0, 0), false); + self.* = initC(builder, name, Kind.Exe, builder.version(0, 0, 0), false); return self; } - fn initExtraArgs(builder: &Builder, name: []const u8, root_src: ?[]const u8, kind: Kind, - static: bool, ver: &const Version) LibExeObjStep - { - var self = LibExeObjStep { + fn initExtraArgs(builder: &Builder, name: []const u8, root_src: ?[]const u8, kind: Kind, static: bool, ver: &const Version) LibExeObjStep { + var self = LibExeObjStep{ .strip = false, .builder = builder, .verbose_link = false, @@ -930,7 +915,7 @@ pub const LibExeObjStep = struct { .step = Step.init(name, builder.allocator, make), .output_path = null, .output_h_path = null, - .version = *ver, + .version = ver.*, .out_filename = undefined, .out_h_filename = builder.fmt("{}.h", name), .major_only_filename = undefined, @@ -953,11 +938,11 @@ pub const LibExeObjStep = struct { } fn initC(builder: &Builder, name: []const u8, kind: Kind, version: &const Version, static: bool) LibExeObjStep { - var self = LibExeObjStep { + var self = LibExeObjStep{ .builder = builder, .name = name, .kind = kind, - .version = *version, + .version = version.*, .static = static, .target = Target.Native, .cflags = ArrayList([]const u8).init(builder.allocator), @@ -1005,9 +990,9 @@ pub const LibExeObjStep = struct { self.out_filename = self.builder.fmt("lib{}.a", self.name); } else { switch (self.target.getOs()) { - builtin.Os.ios, builtin.Os.macosx => { - self.out_filename = self.builder.fmt("lib{}.{d}.{d}.{d}.dylib", - self.name, self.version.major, self.version.minor, self.version.patch); + builtin.Os.ios, + builtin.Os.macosx => { + self.out_filename = self.builder.fmt("lib{}.{d}.{d}.{d}.dylib", self.name, self.version.major, self.version.minor, self.version.patch); self.major_only_filename = self.builder.fmt("lib{}.{d}.dylib", self.name, self.version.major); self.name_only_filename = self.builder.fmt("lib{}.dylib", self.name); }, @@ -1015,8 +1000,7 @@ pub const LibExeObjStep = struct { self.out_filename = self.builder.fmt("{}.dll", self.name); }, else => { - self.out_filename = self.builder.fmt("lib{}.so.{d}.{d}.{d}", - self.name, self.version.major, self.version.minor, self.version.patch); + self.out_filename = self.builder.fmt("lib{}.so.{d}.{d}.{d}", self.name, self.version.major, self.version.minor, self.version.patch); self.major_only_filename = self.builder.fmt("lib{}.so.{d}", self.name, self.version.major); self.name_only_filename = self.builder.fmt("lib{}.so", self.name); }, @@ -1026,16 +1010,12 @@ pub const LibExeObjStep = struct { } } - pub fn setTarget(self: &LibExeObjStep, target_arch: builtin.Arch, target_os: builtin.Os, - target_environ: builtin.Environ) void - { - self.target = Target { - .Cross = CrossTarget { - .arch = target_arch, - .os = target_os, - .environ = target_environ, - } - }; + pub fn setTarget(self: &LibExeObjStep, target_arch: builtin.Arch, target_os: builtin.Os, target_environ: builtin.Environ) void { + self.target = Target{ .Cross = CrossTarget{ + .arch = target_arch, + .os = target_os, + .environ = target_environ, + } }; self.computeOutFileNames(); } @@ -1159,7 +1139,7 @@ pub const LibExeObjStep = struct { pub fn addPackagePath(self: &LibExeObjStep, name: []const u8, pkg_index_path: []const u8) void { assert(self.is_zig); - self.packages.append(Pkg { + self.packages.append(Pkg{ .name = name, .path = pkg_index_path, }) catch unreachable; @@ -1343,8 +1323,7 @@ pub const LibExeObjStep = struct { try builder.spawnChild(zig_args.toSliceConst()); if (self.kind == Kind.Lib and !self.static and self.target.wantSharedLibSymLinks()) { - try doAtomicSymLinks(builder.allocator, output_path, self.major_only_filename, - self.name_only_filename); + try doAtomicSymLinks(builder.allocator, output_path, self.major_only_filename, self.name_only_filename); } } @@ -1373,7 +1352,8 @@ pub const LibExeObjStep = struct { args.append("ssp-buffer-size=4") catch unreachable; } }, - builtin.Mode.ReleaseFast, builtin.Mode.ReleaseSmall => { + builtin.Mode.ReleaseFast, + builtin.Mode.ReleaseSmall => { args.append("-O2") catch unreachable; args.append("-fno-stack-protector") catch unreachable; }, @@ -1505,8 +1485,7 @@ pub const LibExeObjStep = struct { } if (!is_darwin) { - const rpath_arg = builder.fmt("-Wl,-rpath,{}", - os.path.real(builder.allocator, builder.pathFromRoot(builder.cache_root)) catch unreachable); + const rpath_arg = builder.fmt("-Wl,-rpath,{}", os.path.real(builder.allocator, builder.pathFromRoot(builder.cache_root)) catch unreachable); defer builder.allocator.free(rpath_arg); cc_args.append(rpath_arg) catch unreachable; @@ -1535,8 +1514,7 @@ pub const LibExeObjStep = struct { try builder.spawnChild(cc_args.toSliceConst()); if (self.target.wantSharedLibSymLinks()) { - try doAtomicSymLinks(builder.allocator, output_path, self.major_only_filename, - self.name_only_filename); + try doAtomicSymLinks(builder.allocator, output_path, self.major_only_filename, self.name_only_filename); } } }, @@ -1581,8 +1559,7 @@ pub const LibExeObjStep = struct { cc_args.append("-o") catch unreachable; cc_args.append(output_path) catch unreachable; - const rpath_arg = builder.fmt("-Wl,-rpath,{}", - os.path.real(builder.allocator, builder.pathFromRoot(builder.cache_root)) catch unreachable); + const rpath_arg = builder.fmt("-Wl,-rpath,{}", os.path.real(builder.allocator, builder.pathFromRoot(builder.cache_root)) catch unreachable); defer builder.allocator.free(rpath_arg); cc_args.append(rpath_arg) catch unreachable; @@ -1635,7 +1612,7 @@ pub const TestStep = struct { pub fn init(builder: &Builder, root_src: []const u8) TestStep { const step_name = builder.fmt("test {}", root_src); - return TestStep { + return TestStep{ .step = Step.init(step_name, builder.allocator, make), .builder = builder, .root_src = root_src, @@ -1644,7 +1621,7 @@ pub const TestStep = struct { .name_prefix = "", .filter = null, .link_libs = BufSet.init(builder.allocator), - .target = Target { .Native = {} }, + .target = Target{ .Native = {} }, .exec_cmd_args = null, .include_dirs = ArrayList([]const u8).init(builder.allocator), }; @@ -1674,16 +1651,12 @@ pub const TestStep = struct { self.filter = text; } - pub fn setTarget(self: &TestStep, target_arch: builtin.Arch, target_os: builtin.Os, - target_environ: builtin.Environ) void - { - self.target = Target { - .Cross = CrossTarget { - .arch = target_arch, - .os = target_os, - .environ = target_environ, - } - }; + pub fn setTarget(self: &TestStep, target_arch: builtin.Arch, target_os: builtin.Os, target_environ: builtin.Environ) void { + self.target = Target{ .Cross = CrossTarget{ + .arch = target_arch, + .os = target_os, + .environ = target_environ, + } }; } pub fn setExecCmd(self: &TestStep, args: []const ?[]const u8) void { @@ -1789,11 +1762,9 @@ pub const CommandStep = struct { env_map: &const BufMap, /// ::argv is copied. - pub fn create(builder: &Builder, cwd: ?[]const u8, env_map: &const BufMap, - argv: []const []const u8) &CommandStep - { + pub fn create(builder: &Builder, cwd: ?[]const u8, env_map: &const BufMap, argv: []const []const u8) &CommandStep { const self = builder.allocator.create(CommandStep) catch unreachable; - *self = CommandStep { + self.* = CommandStep{ .builder = builder, .step = Step.init(argv[0], builder.allocator, make), .argv = builder.allocator.alloc([]u8, argv.len) catch unreachable, @@ -1828,7 +1799,7 @@ const InstallArtifactStep = struct { LibExeObjStep.Kind.Exe => builder.exe_dir, LibExeObjStep.Kind.Lib => builder.lib_dir, }; - *self = Self { + self.* = Self{ .builder = builder, .step = Step.init(builder.fmt("install {}", artifact.step.name), builder.allocator, make), .artifact = artifact, @@ -1837,10 +1808,8 @@ const InstallArtifactStep = struct { self.step.dependOn(&artifact.step); builder.pushInstalledFile(self.dest_file); if (self.artifact.kind == LibExeObjStep.Kind.Lib and !self.artifact.static) { - builder.pushInstalledFile(os.path.join(builder.allocator, builder.lib_dir, - artifact.major_only_filename) catch unreachable); - builder.pushInstalledFile(os.path.join(builder.allocator, builder.lib_dir, - artifact.name_only_filename) catch unreachable); + builder.pushInstalledFile(os.path.join(builder.allocator, builder.lib_dir, artifact.major_only_filename) catch unreachable); + builder.pushInstalledFile(os.path.join(builder.allocator, builder.lib_dir, artifact.name_only_filename) catch unreachable); } return self; } @@ -1859,8 +1828,7 @@ const InstallArtifactStep = struct { }; try builder.copyFileMode(self.artifact.getOutputPath(), self.dest_file, mode); if (self.artifact.kind == LibExeObjStep.Kind.Lib and !self.artifact.static) { - try doAtomicSymLinks(builder.allocator, self.dest_file, - self.artifact.major_only_filename, self.artifact.name_only_filename); + try doAtomicSymLinks(builder.allocator, self.dest_file, self.artifact.major_only_filename, self.artifact.name_only_filename); } } }; @@ -1872,7 +1840,7 @@ pub const InstallFileStep = struct { dest_path: []const u8, pub fn init(builder: &Builder, src_path: []const u8, dest_path: []const u8) InstallFileStep { - return InstallFileStep { + return InstallFileStep{ .builder = builder, .step = Step.init(builder.fmt("install {}", src_path), builder.allocator, make), .src_path = src_path, @@ -1893,7 +1861,7 @@ pub const WriteFileStep = struct { data: []const u8, pub fn init(builder: &Builder, file_path: []const u8, data: []const u8) WriteFileStep { - return WriteFileStep { + return WriteFileStep{ .builder = builder, .step = Step.init(builder.fmt("writefile {}", file_path), builder.allocator, make), .file_path = file_path, @@ -1922,7 +1890,7 @@ pub const LogStep = struct { data: []const u8, pub fn init(builder: &Builder, data: []const u8) LogStep { - return LogStep { + return LogStep{ .builder = builder, .step = Step.init(builder.fmt("log {}", data), builder.allocator, make), .data = data, @@ -1941,7 +1909,7 @@ pub const RemoveDirStep = struct { dir_path: []const u8, pub fn init(builder: &Builder, dir_path: []const u8) RemoveDirStep { - return RemoveDirStep { + return RemoveDirStep{ .builder = builder, .step = Step.init(builder.fmt("RemoveDir {}", dir_path), builder.allocator, make), .dir_path = dir_path, @@ -1966,8 +1934,8 @@ pub const Step = struct { loop_flag: bool, done_flag: bool, - pub fn init(name: []const u8, allocator: &Allocator, makeFn: fn (&Step)error!void) Step { - return Step { + pub fn init(name: []const u8, allocator: &Allocator, makeFn: fn(&Step) error!void) Step { + return Step{ .name = name, .makeFn = makeFn, .dependencies = ArrayList(&Step).init(allocator), @@ -1980,8 +1948,7 @@ pub const Step = struct { } pub fn make(self: &Step) !void { - if (self.done_flag) - return; + if (self.done_flag) return; try self.makeFn(self); self.done_flag = true; @@ -1994,9 +1961,7 @@ pub const Step = struct { fn makeNoOp(self: &Step) error!void {} }; -fn doAtomicSymLinks(allocator: &Allocator, output_path: []const u8, filename_major_only: []const u8, - filename_name_only: []const u8) !void -{ +fn doAtomicSymLinks(allocator: &Allocator, output_path: []const u8, filename_major_only: []const u8, filename_name_only: []const u8) !void { const out_dir = os.path.dirname(output_path); const out_basename = os.path.basename(output_path); // sym link for libfoo.so.1 to libfoo.so.1.2.3 diff --git a/std/crypto/blake2.zig b/std/crypto/blake2.zig index 99f0e629cd7b72caf727ef905df09be27ed0d244..18025d08eb0d7ff0693dab87adadf5be6146c44c 100644 --- a/std/crypto/blake2.zig +++ b/std/crypto/blake2.zig @@ -6,11 +6,23 @@ const builtin = @import("builtin"); const htest = @import("test.zig"); const RoundParam = struct { - a: usize, b: usize, c: usize, d: usize, x: usize, y: usize, + a: usize, + b: usize, + c: usize, + d: usize, + x: usize, + y: usize, }; fn Rp(a: usize, b: usize, c: usize, d: usize, x: usize, y: usize) RoundParam { - return RoundParam { .a = a, .b = b, .c = c, .d = d, .x = x, .y = y, }; + return RoundParam{ + .a = a, + .b = b, + .c = c, + .d = d, + .x = x, + .y = y, + }; } ///////////////////// @@ -19,145 +31,153 @@ fn Rp(a: usize, b: usize, c: usize, d: usize, x: usize, y: usize) RoundParam { pub const Blake2s224 = Blake2s(224); pub const Blake2s256 = Blake2s(256); -fn Blake2s(comptime out_len: usize) type { return struct { - const Self = this; - const block_size = 64; - const digest_size = out_len / 8; - - const iv = [8]u32 { - 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, - 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19, - }; - - const sigma = [10][16]u8 { - []const u8 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, - []const u8 { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }, - []const u8 { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 }, - []const u8 { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 }, - []const u8 { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 }, - []const u8 { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 }, - []const u8 { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 }, - []const u8 { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 }, - []const u8 { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 }, - []const u8 { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 }, - }; - - h: [8]u32, - t: u64, - // Streaming cache - buf: [64]u8, - buf_len: u8, - - pub fn init() Self { - debug.assert(8 <= out_len and out_len <= 512); - - var s: Self = undefined; - s.reset(); - return s; - } - - pub fn reset(d: &Self) void { - mem.copy(u32, d.h[0..], iv[0..]); - - // No key plus default parameters - d.h[0] ^= 0x01010000 ^ u32(out_len >> 3); - d.t = 0; - d.buf_len = 0; - } - - pub fn hash(b: []const u8, out: []u8) void { - var d = Self.init(); - d.update(b); - d.final(out); - } - - pub fn update(d: &Self, b: []const u8) void { - var off: usize = 0; - - // Partial buffer exists from previous update. Copy into buffer then hash. - if (d.buf_len != 0 and d.buf_len + b.len > 64) { - off += 64 - d.buf_len; - mem.copy(u8, d.buf[d.buf_len..], b[0..off]); - d.t += 64; - d.round(d.buf[0..], false); +fn Blake2s(comptime out_len: usize) type { + return struct { + const Self = this; + const block_size = 64; + const digest_size = out_len / 8; + + const iv = [8]u32{ + 0x6A09E667, + 0xBB67AE85, + 0x3C6EF372, + 0xA54FF53A, + 0x510E527F, + 0x9B05688C, + 0x1F83D9AB, + 0x5BE0CD19, + }; + + const sigma = [10][16]u8{ + []const u8 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, + []const u8 { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }, + []const u8 { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 }, + []const u8 { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 }, + []const u8 { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 }, + []const u8 { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 }, + []const u8 { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 }, + []const u8 { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 }, + []const u8 { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 }, + []const u8 { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 }, + }; + + h: [8]u32, + t: u64, + // Streaming cache + buf: [64]u8, + buf_len: u8, + + pub fn init() Self { + debug.assert(8 <= out_len and out_len <= 512); + + var s: Self = undefined; + s.reset(); + return s; + } + + pub fn reset(d: &Self) void { + mem.copy(u32, d.h[0..], iv[0..]); + + // No key plus default parameters + d.h[0] ^= 0x01010000 ^ u32(out_len >> 3); + d.t = 0; d.buf_len = 0; } - // Full middle blocks. - while (off + 64 <= b.len) : (off += 64) { - d.t += 64; - d.round(b[off..off + 64], false); + pub fn hash(b: []const u8, out: []u8) void { + var d = Self.init(); + d.update(b); + d.final(out); } - // Copy any remainder for next pass. - mem.copy(u8, d.buf[d.buf_len..], b[off..]); - d.buf_len += u8(b[off..].len); - } + pub fn update(d: &Self, b: []const u8) void { + var off: usize = 0; - pub fn final(d: &Self, out: []u8) void { - debug.assert(out.len >= out_len / 8); - - mem.set(u8, d.buf[d.buf_len..], 0); - d.t += d.buf_len; - d.round(d.buf[0..], true); + // Partial buffer exists from previous update. Copy into buffer then hash. + if (d.buf_len != 0 and d.buf_len + b.len > 64) { + off += 64 - d.buf_len; + mem.copy(u8, d.buf[d.buf_len..], b[0..off]); + d.t += 64; + d.round(d.buf[0..], false); + d.buf_len = 0; + } - const rr = d.h[0 .. out_len / 32]; + // Full middle blocks. + while (off + 64 <= b.len) : (off += 64) { + d.t += 64; + d.round(b[off..off + 64], false); + } - for (rr) |s, j| { - mem.writeInt(out[4*j .. 4*j + 4], s, builtin.Endian.Little); + // Copy any remainder for next pass. + mem.copy(u8, d.buf[d.buf_len..], b[off..]); + d.buf_len += u8(b[off..].len); } - } - fn round(d: &Self, b: []const u8, last: bool) void { - debug.assert(b.len == 64); + pub fn final(d: &Self, out: []u8) void { + debug.assert(out.len >= out_len / 8); - var m: [16]u32 = undefined; - var v: [16]u32 = undefined; + mem.set(u8, d.buf[d.buf_len..], 0); + d.t += d.buf_len; + d.round(d.buf[0..], true); - for (m) |*r, i| { - *r = mem.readIntLE(u32, b[4*i .. 4*i + 4]); - } + const rr = d.h[0..out_len / 32]; - var k: usize = 0; - while (k < 8) : (k += 1) { - v[k] = d.h[k]; - v[k+8] = iv[k]; + for (rr) |s, j| { + mem.writeInt(out[4 * j..4 * j + 4], s, builtin.Endian.Little); + } } - v[12] ^= @truncate(u32, d.t); - v[13] ^= u32(d.t >> 32); - if (last) v[14] = ~v[14]; - - const rounds = comptime []RoundParam { - Rp(0, 4, 8, 12, 0, 1), - Rp(1, 5, 9, 13, 2, 3), - Rp(2, 6, 10, 14, 4, 5), - Rp(3, 7, 11, 15, 6, 7), - Rp(0, 5, 10, 15, 8, 9), - Rp(1, 6, 11, 12, 10, 11), - Rp(2, 7, 8, 13, 12, 13), - Rp(3, 4, 9, 14, 14, 15), - }; - - comptime var j: usize = 0; - inline while (j < 10) : (j += 1) { - inline for (rounds) |r| { - v[r.a] = v[r.a] +% v[r.b] +% m[sigma[j][r.x]]; - v[r.d] = math.rotr(u32, v[r.d] ^ v[r.a], usize(16)); - v[r.c] = v[r.c] +% v[r.d]; - v[r.b] = math.rotr(u32, v[r.b] ^ v[r.c], usize(12)); - v[r.a] = v[r.a] +% v[r.b] +% m[sigma[j][r.y]]; - v[r.d] = math.rotr(u32, v[r.d] ^ v[r.a], usize(8)); - v[r.c] = v[r.c] +% v[r.d]; - v[r.b] = math.rotr(u32, v[r.b] ^ v[r.c], usize(7)); + fn round(d: &Self, b: []const u8, last: bool) void { + debug.assert(b.len == 64); + + var m: [16]u32 = undefined; + var v: [16]u32 = undefined; + + for (m) |*r, i| { + r.* = mem.readIntLE(u32, b[4 * i..4 * i + 4]); } - } - for (d.h) |*r, i| { - *r ^= v[i] ^ v[i + 8]; + var k: usize = 0; + while (k < 8) : (k += 1) { + v[k] = d.h[k]; + v[k + 8] = iv[k]; + } + + v[12] ^= @truncate(u32, d.t); + v[13] ^= u32(d.t >> 32); + if (last) v[14] = ~v[14]; + + const rounds = comptime []RoundParam{ + Rp(0, 4, 8, 12, 0, 1), + Rp(1, 5, 9, 13, 2, 3), + Rp(2, 6, 10, 14, 4, 5), + Rp(3, 7, 11, 15, 6, 7), + Rp(0, 5, 10, 15, 8, 9), + Rp(1, 6, 11, 12, 10, 11), + Rp(2, 7, 8, 13, 12, 13), + Rp(3, 4, 9, 14, 14, 15), + }; + + comptime var j: usize = 0; + inline while (j < 10) : (j += 1) { + inline for (rounds) |r| { + v[r.a] = v[r.a] +% v[r.b] +% m[sigma[j][r.x]]; + v[r.d] = math.rotr(u32, v[r.d] ^ v[r.a], usize(16)); + v[r.c] = v[r.c] +% v[r.d]; + v[r.b] = math.rotr(u32, v[r.b] ^ v[r.c], usize(12)); + v[r.a] = v[r.a] +% v[r.b] +% m[sigma[j][r.y]]; + v[r.d] = math.rotr(u32, v[r.d] ^ v[r.a], usize(8)); + v[r.c] = v[r.c] +% v[r.d]; + v[r.b] = math.rotr(u32, v[r.b] ^ v[r.c], usize(7)); + } + } + + for (d.h) |*r, i| { + r.* ^= v[i] ^ v[i + 8]; + } } - } -};} + }; +} test "blake2s224 single" { const h1 = "1fa1291e65248b37b3433475b2a0dd63d54a11ecc4e3e034e7bc1ef4"; @@ -230,7 +250,7 @@ test "blake2s256 streaming" { } test "blake2s256 aligned final" { - var block = []u8 {0} ** Blake2s256.block_size; + var block = []u8{0} ** Blake2s256.block_size; var out: [Blake2s256.digest_size]u8 = undefined; var h = Blake2s256.init(); @@ -238,154 +258,363 @@ test "blake2s256 aligned final" { h.final(out[0..]); } - ///////////////////// // Blake2b pub const Blake2b384 = Blake2b(384); pub const Blake2b512 = Blake2b(512); -fn Blake2b(comptime out_len: usize) type { return struct { - const Self = this; - const block_size = 128; - const digest_size = out_len / 8; +fn Blake2b(comptime out_len: usize) type { + return struct { + const Self = this; + const block_size = 128; + const digest_size = out_len / 8; - const iv = [8]u64 { - 0x6a09e667f3bcc908, 0xbb67ae8584caa73b, - 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1, - 0x510e527fade682d1, 0x9b05688c2b3e6c1f, - 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179, - }; + const iv = [8]u64{ + 0x6a09e667f3bcc908, + 0xbb67ae8584caa73b, + 0x3c6ef372fe94f82b, + 0xa54ff53a5f1d36f1, + 0x510e527fade682d1, + 0x9b05688c2b3e6c1f, + 0x1f83d9abfb41bd6b, + 0x5be0cd19137e2179, + }; - const sigma = [12][16]u8 { - []const u8 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, - []const u8 { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }, - []const u8 { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 }, - []const u8 { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 }, - []const u8 { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 }, - []const u8 { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 }, - []const u8 { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 }, - []const u8 { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 }, - []const u8 { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 }, - []const u8 { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 }, - []const u8 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, - []const u8 { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }, - }; + const sigma = [12][16]u8{ + []const u8{ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + }, + []const u8{ + 14, + 10, + 4, + 8, + 9, + 15, + 13, + 6, + 1, + 12, + 0, + 2, + 11, + 7, + 5, + 3, + }, + []const u8{ + 11, + 8, + 12, + 0, + 5, + 2, + 15, + 13, + 10, + 14, + 3, + 6, + 7, + 1, + 9, + 4, + }, + []const u8{ + 7, + 9, + 3, + 1, + 13, + 12, + 11, + 14, + 2, + 6, + 5, + 10, + 4, + 0, + 15, + 8, + }, + []const u8{ + 9, + 0, + 5, + 7, + 2, + 4, + 10, + 15, + 14, + 1, + 11, + 12, + 6, + 8, + 3, + 13, + }, + []const u8{ + 2, + 12, + 6, + 10, + 0, + 11, + 8, + 3, + 4, + 13, + 7, + 5, + 15, + 14, + 1, + 9, + }, + []const u8{ + 12, + 5, + 1, + 15, + 14, + 13, + 4, + 10, + 0, + 7, + 6, + 3, + 9, + 2, + 8, + 11, + }, + []const u8{ + 13, + 11, + 7, + 14, + 12, + 1, + 3, + 9, + 5, + 0, + 15, + 4, + 8, + 6, + 2, + 10, + }, + []const u8{ + 6, + 15, + 14, + 9, + 11, + 3, + 0, + 8, + 12, + 2, + 13, + 7, + 1, + 4, + 10, + 5, + }, + []const u8{ + 10, + 2, + 8, + 4, + 7, + 6, + 1, + 5, + 15, + 11, + 9, + 14, + 3, + 12, + 13, + 0, + }, + []const u8{ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + }, + []const u8{ + 14, + 10, + 4, + 8, + 9, + 15, + 13, + 6, + 1, + 12, + 0, + 2, + 11, + 7, + 5, + 3, + }, + }; - h: [8]u64, - t: u128, - // Streaming cache - buf: [128]u8, - buf_len: u8, + h: [8]u64, + t: u128, + // Streaming cache + buf: [128]u8, + buf_len: u8, - pub fn init() Self { - debug.assert(8 <= out_len and out_len <= 512); + pub fn init() Self { + debug.assert(8 <= out_len and out_len <= 512); - var s: Self = undefined; - s.reset(); - return s; - } + var s: Self = undefined; + s.reset(); + return s; + } - pub fn reset(d: &Self) void { - mem.copy(u64, d.h[0..], iv[0..]); + pub fn reset(d: &Self) void { + mem.copy(u64, d.h[0..], iv[0..]); - // No key plus default parameters - d.h[0] ^= 0x01010000 ^ (out_len >> 3); - d.t = 0; - d.buf_len = 0; - } - - pub fn hash(b: []const u8, out: []u8) void { - var d = Self.init(); - d.update(b); - d.final(out); - } - - pub fn update(d: &Self, b: []const u8) void { - var off: usize = 0; - - // Partial buffer exists from previous update. Copy into buffer then hash. - if (d.buf_len != 0 and d.buf_len + b.len > 128) { - off += 128 - d.buf_len; - mem.copy(u8, d.buf[d.buf_len..], b[0..off]); - d.t += 128; - d.round(d.buf[0..], false); + // No key plus default parameters + d.h[0] ^= 0x01010000 ^ (out_len >> 3); + d.t = 0; d.buf_len = 0; } - // Full middle blocks. - while (off + 128 <= b.len) : (off += 128) { - d.t += 128; - d.round(b[off..off + 128], false); + pub fn hash(b: []const u8, out: []u8) void { + var d = Self.init(); + d.update(b); + d.final(out); } - // Copy any remainder for next pass. - mem.copy(u8, d.buf[d.buf_len..], b[off..]); - d.buf_len += u8(b[off..].len); - } + pub fn update(d: &Self, b: []const u8) void { + var off: usize = 0; - pub fn final(d: &Self, out: []u8) void { - mem.set(u8, d.buf[d.buf_len..], 0); - d.t += d.buf_len; - d.round(d.buf[0..], true); + // Partial buffer exists from previous update. Copy into buffer then hash. + if (d.buf_len != 0 and d.buf_len + b.len > 128) { + off += 128 - d.buf_len; + mem.copy(u8, d.buf[d.buf_len..], b[0..off]); + d.t += 128; + d.round(d.buf[0..], false); + d.buf_len = 0; + } - const rr = d.h[0 .. out_len / 64]; + // Full middle blocks. + while (off + 128 <= b.len) : (off += 128) { + d.t += 128; + d.round(b[off..off + 128], false); + } - for (rr) |s, j| { - mem.writeInt(out[8*j .. 8*j + 8], s, builtin.Endian.Little); + // Copy any remainder for next pass. + mem.copy(u8, d.buf[d.buf_len..], b[off..]); + d.buf_len += u8(b[off..].len); } - } - fn round(d: &Self, b: []const u8, last: bool) void { - debug.assert(b.len == 128); + pub fn final(d: &Self, out: []u8) void { + mem.set(u8, d.buf[d.buf_len..], 0); + d.t += d.buf_len; + d.round(d.buf[0..], true); - var m: [16]u64 = undefined; - var v: [16]u64 = undefined; + const rr = d.h[0..out_len / 64]; - for (m) |*r, i| { - *r = mem.readIntLE(u64, b[8*i .. 8*i + 8]); + for (rr) |s, j| { + mem.writeInt(out[8 * j..8 * j + 8], s, builtin.Endian.Little); + } } - var k: usize = 0; - while (k < 8) : (k += 1) { - v[k] = d.h[k]; - v[k+8] = iv[k]; - } + fn round(d: &Self, b: []const u8, last: bool) void { + debug.assert(b.len == 128); - v[12] ^= @truncate(u64, d.t); - v[13] ^= u64(d.t >> 64); - if (last) v[14] = ~v[14]; + var m: [16]u64 = undefined; + var v: [16]u64 = undefined; - const rounds = comptime []RoundParam { - Rp(0, 4, 8, 12, 0, 1), - Rp(1, 5, 9, 13, 2, 3), - Rp(2, 6, 10, 14, 4, 5), - Rp(3, 7, 11, 15, 6, 7), - Rp(0, 5, 10, 15, 8, 9), - Rp(1, 6, 11, 12, 10, 11), - Rp(2, 7, 8, 13, 12, 13), - Rp(3, 4, 9, 14, 14, 15), - }; + for (m) |*r, i| { + r.* = mem.readIntLE(u64, b[8 * i..8 * i + 8]); + } - comptime var j: usize = 0; - inline while (j < 12) : (j += 1) { - inline for (rounds) |r| { - v[r.a] = v[r.a] +% v[r.b] +% m[sigma[j][r.x]]; - v[r.d] = math.rotr(u64, v[r.d] ^ v[r.a], usize(32)); - v[r.c] = v[r.c] +% v[r.d]; - v[r.b] = math.rotr(u64, v[r.b] ^ v[r.c], usize(24)); - v[r.a] = v[r.a] +% v[r.b] +% m[sigma[j][r.y]]; - v[r.d] = math.rotr(u64, v[r.d] ^ v[r.a], usize(16)); - v[r.c] = v[r.c] +% v[r.d]; - v[r.b] = math.rotr(u64, v[r.b] ^ v[r.c], usize(63)); + var k: usize = 0; + while (k < 8) : (k += 1) { + v[k] = d.h[k]; + v[k + 8] = iv[k]; } - } - for (d.h) |*r, i| { - *r ^= v[i] ^ v[i + 8]; + v[12] ^= @truncate(u64, d.t); + v[13] ^= u64(d.t >> 64); + if (last) v[14] = ~v[14]; + + const rounds = comptime []RoundParam{ + Rp(0, 4, 8, 12, 0, 1), + Rp(1, 5, 9, 13, 2, 3), + Rp(2, 6, 10, 14, 4, 5), + Rp(3, 7, 11, 15, 6, 7), + Rp(0, 5, 10, 15, 8, 9), + Rp(1, 6, 11, 12, 10, 11), + Rp(2, 7, 8, 13, 12, 13), + Rp(3, 4, 9, 14, 14, 15), + }; + + comptime var j: usize = 0; + inline while (j < 12) : (j += 1) { + inline for (rounds) |r| { + v[r.a] = v[r.a] +% v[r.b] +% m[sigma[j][r.x]]; + v[r.d] = math.rotr(u64, v[r.d] ^ v[r.a], usize(32)); + v[r.c] = v[r.c] +% v[r.d]; + v[r.b] = math.rotr(u64, v[r.b] ^ v[r.c], usize(24)); + v[r.a] = v[r.a] +% v[r.b] +% m[sigma[j][r.y]]; + v[r.d] = math.rotr(u64, v[r.d] ^ v[r.a], usize(16)); + v[r.c] = v[r.c] +% v[r.d]; + v[r.b] = math.rotr(u64, v[r.b] ^ v[r.c], usize(63)); + } + } + + for (d.h) |*r, i| { + r.* ^= v[i] ^ v[i + 8]; + } } - } -};} + }; +} test "blake2b384 single" { const h1 = "b32811423377f52d7862286ee1a72ee540524380fda1724a6f25d7978c6fd3244a6caf0498812673c5e05ef583825100"; @@ -458,7 +687,7 @@ test "blake2b512 streaming" { } test "blake2b512 aligned final" { - var block = []u8 {0} ** Blake2b512.block_size; + var block = []u8{0} ** Blake2b512.block_size; var out: [Blake2b512.digest_size]u8 = undefined; var h = Blake2b512.init(); diff --git a/std/crypto/hmac.zig b/std/crypto/hmac.zig index 2a36f15b7159149d07020198f8f87bf946c7d013..1415e88cf41483554c4bd89693b9f1fece032293 100644 --- a/std/crypto/hmac.zig +++ b/std/crypto/hmac.zig @@ -29,12 +29,12 @@ pub fn Hmac(comptime H: type) type { var o_key_pad: [H.block_size]u8 = undefined; for (o_key_pad) |*b, i| { - *b = scratch[i] ^ 0x5c; + b.* = scratch[i] ^ 0x5c; } var i_key_pad: [H.block_size]u8 = undefined; for (i_key_pad) |*b, i| { - *b = scratch[i] ^ 0x36; + b.* = scratch[i] ^ 0x36; } // HMAC(k, m) = H(o_key_pad | H(i_key_pad | message)) where | is concatenation diff --git a/std/crypto/sha3.zig b/std/crypto/sha3.zig index f92f56d68f292890fdbcc9164f2459de51682c80..73b6415e1d8f8593c6cf0d59a44646d24867f514 100644 --- a/std/crypto/sha3.zig +++ b/std/crypto/sha3.zig @@ -10,148 +10,228 @@ pub const Sha3_256 = Keccak(256, 0x06); pub const Sha3_384 = Keccak(384, 0x06); pub const Sha3_512 = Keccak(512, 0x06); -fn Keccak(comptime bits: usize, comptime delim: u8) type { return struct { - const Self = this; - const block_size = 200; - const digest_size = bits / 8; - - s: [200]u8, - offset: usize, - rate: usize, - - pub fn init() Self { - var d: Self = undefined; - d.reset(); - return d; - } - - pub fn reset(d: &Self) void { - mem.set(u8, d.s[0..], 0); - d.offset = 0; - d.rate = 200 - (bits / 4); - } - - pub fn hash(b: []const u8, out: []u8) void { - var d = Self.init(); - d.update(b); - d.final(out); - } - - pub fn update(d: &Self, b: []const u8) void { - var ip: usize = 0; - var len = b.len; - var rate = d.rate - d.offset; - var offset = d.offset; - - // absorb - while (len >= rate) { - for (d.s[offset .. offset + rate]) |*r, i| - *r ^= b[ip..][i]; +fn Keccak(comptime bits: usize, comptime delim: u8) type { + return struct { + const Self = this; + const block_size = 200; + const digest_size = bits / 8; + + s: [200]u8, + offset: usize, + rate: usize, + + pub fn init() Self { + var d: Self = undefined; + d.reset(); + return d; + } - keccak_f(1600, d.s[0..]); + pub fn reset(d: &Self) void { + mem.set(u8, d.s[0..], 0); + d.offset = 0; + d.rate = 200 - (bits / 4); + } - ip += rate; - len -= rate; - rate = d.rate; - offset = 0; + pub fn hash(b: []const u8, out: []u8) void { + var d = Self.init(); + d.update(b); + d.final(out); } - for (d.s[offset .. offset + len]) |*r, i| - *r ^= b[ip..][i]; + pub fn update(d: &Self, b: []const u8) void { + var ip: usize = 0; + var len = b.len; + var rate = d.rate - d.offset; + var offset = d.offset; - d.offset = offset + len; - } + // absorb + while (len >= rate) { + for (d.s[offset..offset + rate]) |*r, i| + r.* ^= b[ip..][i]; - pub fn final(d: &Self, out: []u8) void { - // padding - d.s[d.offset] ^= delim; - d.s[d.rate - 1] ^= 0x80; + keccak_f(1600, d.s[0..]); - keccak_f(1600, d.s[0..]); + ip += rate; + len -= rate; + rate = d.rate; + offset = 0; + } - // squeeze - var op: usize = 0; - var len: usize = bits / 8; + for (d.s[offset..offset + len]) |*r, i| + r.* ^= b[ip..][i]; - while (len >= d.rate) { - mem.copy(u8, out[op..], d.s[0..d.rate]); - keccak_f(1600, d.s[0..]); - op += d.rate; - len -= d.rate; + d.offset = offset + len; } - mem.copy(u8, out[op..], d.s[0..len]); - } -};} - -const RC = []const u64 { - 0x0000000000000001, 0x0000000000008082, 0x800000000000808a, 0x8000000080008000, - 0x000000000000808b, 0x0000000080000001, 0x8000000080008081, 0x8000000000008009, - 0x000000000000008a, 0x0000000000000088, 0x0000000080008009, 0x000000008000000a, - 0x000000008000808b, 0x800000000000008b, 0x8000000000008089, 0x8000000000008003, - 0x8000000000008002, 0x8000000000000080, 0x000000000000800a, 0x800000008000000a, - 0x8000000080008081, 0x8000000000008080, 0x0000000080000001, 0x8000000080008008, + pub fn final(d: &Self, out: []u8) void { + // padding + d.s[d.offset] ^= delim; + d.s[d.rate - 1] ^= 0x80; + + keccak_f(1600, d.s[0..]); + + // squeeze + var op: usize = 0; + var len: usize = bits / 8; + + while (len >= d.rate) { + mem.copy(u8, out[op..], d.s[0..d.rate]); + keccak_f(1600, d.s[0..]); + op += d.rate; + len -= d.rate; + } + + mem.copy(u8, out[op..], d.s[0..len]); + } + }; +} + +const RC = []const u64{ + 0x0000000000000001, + 0x0000000000008082, + 0x800000000000808a, + 0x8000000080008000, + 0x000000000000808b, + 0x0000000080000001, + 0x8000000080008081, + 0x8000000000008009, + 0x000000000000008a, + 0x0000000000000088, + 0x0000000080008009, + 0x000000008000000a, + 0x000000008000808b, + 0x800000000000008b, + 0x8000000000008089, + 0x8000000000008003, + 0x8000000000008002, + 0x8000000000000080, + 0x000000000000800a, + 0x800000008000000a, + 0x8000000080008081, + 0x8000000000008080, + 0x0000000080000001, + 0x8000000080008008, }; -const ROTC = []const usize { - 1, 3, 6, 10, 15, 21, 28, 36, - 45, 55, 2, 14, 27, 41, 56, 8, - 25, 43, 62, 18, 39, 61, 20, 44 +const ROTC = []const usize{ + 1, + 3, + 6, + 10, + 15, + 21, + 28, + 36, + 45, + 55, + 2, + 14, + 27, + 41, + 56, + 8, + 25, + 43, + 62, + 18, + 39, + 61, + 20, + 44, }; -const PIL = []const usize { - 10, 7, 11, 17, 18, 3, 5, 16, - 8, 21, 24, 4, 15, 23, 19, 13, - 12, 2, 20, 14, 22, 9, 6, 1 +const PIL = []const usize{ + 10, + 7, + 11, + 17, + 18, + 3, + 5, + 16, + 8, + 21, + 24, + 4, + 15, + 23, + 19, + 13, + 12, + 2, + 20, + 14, + 22, + 9, + 6, + 1, }; -const M5 = []const usize { - 0, 1, 2, 3, 4, 0, 1, 2, 3, 4 +const M5 = []const usize{ + 0, + 1, + 2, + 3, + 4, + 0, + 1, + 2, + 3, + 4, }; fn keccak_f(comptime F: usize, d: []u8) void { debug.assert(d.len == F / 8); const B = F / 25; - const no_rounds = comptime x: { break :x 12 + 2 * math.log2(B); }; + const no_rounds = comptime x: { + break :x 12 + 2 * math.log2(B); + }; - var s = []const u64 {0} ** 25; - var t = []const u64 {0} ** 1; - var c = []const u64 {0} ** 5; + var s = []const u64{0} ** 25; + var t = []const u64{0} ** 1; + var c = []const u64{0} ** 5; for (s) |*r, i| { - *r = mem.readIntLE(u64, d[8*i .. 8*i + 8]); + r.* = mem.readIntLE(u64, d[8 * i..8 * i + 8]); } comptime var x: usize = 0; comptime var y: usize = 0; for (RC[0..no_rounds]) |round| { // theta - x = 0; inline while (x < 5) : (x += 1) { - c[x] = s[x] ^ s[x+5] ^ s[x+10] ^ s[x+15] ^ s[x+20]; + x = 0; + inline while (x < 5) : (x += 1) { + c[x] = s[x] ^ s[x + 5] ^ s[x + 10] ^ s[x + 15] ^ s[x + 20]; } - x = 0; inline while (x < 5) : (x += 1) { - t[0] = c[M5[x+4]] ^ math.rotl(u64, c[M5[x+1]], usize(1)); - y = 0; inline while (y < 5) : (y += 1) { - s[x + y*5] ^= t[0]; + x = 0; + inline while (x < 5) : (x += 1) { + t[0] = c[M5[x + 4]] ^ math.rotl(u64, c[M5[x + 1]], usize(1)); + y = 0; + inline while (y < 5) : (y += 1) { + s[x + y * 5] ^= t[0]; } } // rho+pi t[0] = s[1]; - x = 0; inline while (x < 24) : (x += 1) { + x = 0; + inline while (x < 24) : (x += 1) { c[0] = s[PIL[x]]; s[PIL[x]] = math.rotl(u64, t[0], ROTC[x]); t[0] = c[0]; } // chi - y = 0; inline while (y < 5) : (y += 1) { - x = 0; inline while (x < 5) : (x += 1) { - c[x] = s[x + y*5]; + y = 0; + inline while (y < 5) : (y += 1) { + x = 0; + inline while (x < 5) : (x += 1) { + c[x] = s[x + y * 5]; } - x = 0; inline while (x < 5) : (x += 1) { - s[x + y*5] = c[x] ^ (~c[M5[x+1]] & c[M5[x+2]]); + x = 0; + inline while (x < 5) : (x += 1) { + s[x + y * 5] = c[x] ^ (~c[M5[x + 1]] & c[M5[x + 2]]); } } @@ -160,11 +240,10 @@ fn keccak_f(comptime F: usize, d: []u8) void { } for (s) |r, i| { - mem.writeInt(d[8*i .. 8*i + 8], r, builtin.Endian.Little); + mem.writeInt(d[8 * i..8 * i + 8], r, builtin.Endian.Little); } } - test "sha3-224 single" { htest.assertEqualHash(Sha3_224, "6b4e03423667dbb73b6e15454f0eb1abd4597f9a1b078e3f5b5a6bc7", ""); htest.assertEqualHash(Sha3_224, "e642824c3f8cf24ad09234ee7d3c766fc9a3a5168d0c94ad73b46fdf", "abc"); @@ -192,7 +271,7 @@ test "sha3-224 streaming" { } test "sha3-256 single" { - htest.assertEqualHash(Sha3_256, "a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a" , ""); + htest.assertEqualHash(Sha3_256, "a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a", ""); htest.assertEqualHash(Sha3_256, "3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532", "abc"); htest.assertEqualHash(Sha3_256, "916f6061fe879741ca6469b43971dfdb28b1a32dc36cb3254e812be27aad1d18", "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"); } @@ -218,7 +297,7 @@ test "sha3-256 streaming" { } test "sha3-256 aligned final" { - var block = []u8 {0} ** Sha3_256.block_size; + var block = []u8{0} ** Sha3_256.block_size; var out: [Sha3_256.digest_size]u8 = undefined; var h = Sha3_256.init(); @@ -228,7 +307,7 @@ test "sha3-256 aligned final" { test "sha3-384 single" { const h1 = "0c63a75b845e4f7d01107d852e4c2485c51a50aaaa94fc61995e71bbee983a2ac3713831264adb47fb6bd1e058d5f004"; - htest.assertEqualHash(Sha3_384, h1 , ""); + htest.assertEqualHash(Sha3_384, h1, ""); const h2 = "ec01498288516fc926459f58e2c6ad8df9b473cb0fc08c2596da7cf0e49be4b298d88cea927ac7f539f1edf228376d25"; htest.assertEqualHash(Sha3_384, h2, "abc"); const h3 = "79407d3b5916b59c3e30b09822974791c313fb9ecc849e406f23592d04f625dc8c709b98b43b3852b337216179aa7fc7"; @@ -259,7 +338,7 @@ test "sha3-384 streaming" { test "sha3-512 single" { const h1 = "a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26"; - htest.assertEqualHash(Sha3_512, h1 , ""); + htest.assertEqualHash(Sha3_512, h1, ""); const h2 = "b751850b1a57168a5693cd924b6b096e08f621827444f70d884f5d0240d2712e10e116e9192af3c91a7ec57647e3934057340b4cf408d5a56592f8274eec53f0"; htest.assertEqualHash(Sha3_512, h2, "abc"); const h3 = "afebb2ef542e6579c50cad06d2e578f9f8dd6881d7dc824d26360feebf18a4fa73e3261122948efcfd492e74e82e2189ed0fb440d187f382270cb455f21dd185"; @@ -289,7 +368,7 @@ test "sha3-512 streaming" { } test "sha3-512 aligned final" { - var block = []u8 {0} ** Sha3_512.block_size; + var block = []u8{0} ** Sha3_512.block_size; var out: [Sha3_512.digest_size]u8 = undefined; var h = Sha3_512.init(); diff --git a/std/event.zig b/std/event.zig index bdad7fcc18e9930a5d4157cc5773f14a25b4ddc6..b2e7e3ae381402e10e606e8fdd0ad2e6a3cb4dbf 100644 --- a/std/event.zig +++ b/std/event.zig @@ -6,7 +6,7 @@ const mem = std.mem; const posix = std.os.posix; pub const TcpServer = struct { - handleRequestFn: async<&mem.Allocator> fn (&TcpServer, &const std.net.Address, &const std.os.File) void, + handleRequestFn: async<&mem.Allocator> fn(&TcpServer, &const std.net.Address, &const std.os.File) void, loop: &Loop, sockfd: i32, @@ -18,13 +18,11 @@ pub const TcpServer = struct { const PromiseNode = std.LinkedList(promise).Node; pub fn init(loop: &Loop) !TcpServer { - const sockfd = try std.os.posixSocket(posix.AF_INET, - posix.SOCK_STREAM|posix.SOCK_CLOEXEC|posix.SOCK_NONBLOCK, - posix.PROTO_tcp); + const sockfd = try std.os.posixSocket(posix.AF_INET, posix.SOCK_STREAM | posix.SOCK_CLOEXEC | posix.SOCK_NONBLOCK, posix.PROTO_tcp); errdefer std.os.close(sockfd); // TODO can't initialize handler coroutine here because we need well defined copy elision - return TcpServer { + return TcpServer{ .loop = loop, .sockfd = sockfd, .accept_coro = null, @@ -34,9 +32,7 @@ pub const TcpServer = struct { }; } - pub fn listen(self: &TcpServer, address: &const std.net.Address, - handleRequestFn: async<&mem.Allocator> fn (&TcpServer, &const std.net.Address, &const std.os.File)void) !void - { + pub fn listen(self: &TcpServer, address: &const std.net.Address, handleRequestFn: async<&mem.Allocator> fn(&TcpServer, &const std.net.Address, &const std.os.File) void) !void { self.handleRequestFn = handleRequestFn; try std.os.posixBind(self.sockfd, &address.os_addr); @@ -48,7 +44,6 @@ pub const TcpServer = struct { try self.loop.addFd(self.sockfd, ??self.accept_coro); errdefer self.loop.removeFd(self.sockfd); - } pub fn deinit(self: &TcpServer) void { @@ -60,9 +55,7 @@ pub const TcpServer = struct { pub async fn handler(self: &TcpServer) void { while (true) { var accepted_addr: std.net.Address = undefined; - if (std.os.posixAccept(self.sockfd, &accepted_addr.os_addr, - posix.SOCK_NONBLOCK | posix.SOCK_CLOEXEC)) |accepted_fd| - { + if (std.os.posixAccept(self.sockfd, &accepted_addr.os_addr, posix.SOCK_NONBLOCK | posix.SOCK_CLOEXEC)) |accepted_fd| { var socket = std.os.File.openHandle(accepted_fd); _ = async self.handleRequestFn(self, accepted_addr, socket) catch |err| switch (err) { error.OutOfMemory => { @@ -110,7 +103,7 @@ pub const Loop = struct { fn init(allocator: &mem.Allocator) !Loop { const epollfd = try std.os.linuxEpollCreate(std.os.linux.EPOLL_CLOEXEC); - return Loop { + return Loop{ .keep_running = true, .allocator = allocator, .epollfd = epollfd, @@ -118,11 +111,9 @@ pub const Loop = struct { } pub fn addFd(self: &Loop, fd: i32, prom: promise) !void { - var ev = std.os.linux.epoll_event { - .events = std.os.linux.EPOLLIN|std.os.linux.EPOLLOUT|std.os.linux.EPOLLET, - .data = std.os.linux.epoll_data { - .ptr = @ptrToInt(prom), - }, + var ev = std.os.linux.epoll_event{ + .events = std.os.linux.EPOLLIN | std.os.linux.EPOLLOUT | std.os.linux.EPOLLET, + .data = std.os.linux.epoll_data{ .ptr = @ptrToInt(prom) }, }; try std.os.linuxEpollCtl(self.epollfd, std.os.linux.EPOLL_CTL_ADD, fd, &ev); } @@ -157,9 +148,9 @@ pub const Loop = struct { }; pub async fn connect(loop: &Loop, _address: &const std.net.Address) !std.os.File { - var address = *_address; // TODO https://github.com/zig-lang/zig/issues/733 + var address = _address.*; // TODO https://github.com/zig-lang/zig/issues/733 - const sockfd = try std.os.posixSocket(posix.AF_INET, posix.SOCK_STREAM|posix.SOCK_CLOEXEC|posix.SOCK_NONBLOCK, posix.PROTO_tcp); + const sockfd = try std.os.posixSocket(posix.AF_INET, posix.SOCK_STREAM | posix.SOCK_CLOEXEC | posix.SOCK_NONBLOCK, posix.PROTO_tcp); errdefer std.os.close(sockfd); try std.os.posixConnectAsync(sockfd, &address.os_addr); @@ -179,11 +170,9 @@ test "listen on a port, send bytes, receive bytes" { const Self = this; - async<&mem.Allocator> fn handler(tcp_server: &TcpServer, _addr: &const std.net.Address, - _socket: &const std.os.File) void - { + async<&mem.Allocator> fn handler(tcp_server: &TcpServer, _addr: &const std.net.Address, _socket: &const std.os.File) void { const self = @fieldParentPtr(Self, "tcp_server", tcp_server); - var socket = *_socket; // TODO https://github.com/zig-lang/zig/issues/733 + var socket = _socket.*; // TODO https://github.com/zig-lang/zig/issues/733 defer socket.close(); const next_handler = async errorableHandler(self, _addr, socket) catch |err| switch (err) { error.OutOfMemory => @panic("unable to handle connection: out of memory"), @@ -191,14 +180,14 @@ test "listen on a port, send bytes, receive bytes" { (await next_handler) catch |err| { std.debug.panic("unable to handle connection: {}\n", err); }; - suspend |p| { cancel p; } + suspend |p| { + cancel p; + } } - async fn errorableHandler(self: &Self, _addr: &const std.net.Address, - _socket: &const std.os.File) !void - { - const addr = *_addr; // TODO https://github.com/zig-lang/zig/issues/733 - var socket = *_socket; // TODO https://github.com/zig-lang/zig/issues/733 + async fn errorableHandler(self: &Self, _addr: &const std.net.Address, _socket: &const std.os.File) !void { + const addr = _addr.*; // TODO https://github.com/zig-lang/zig/issues/733 + var socket = _socket.*; // TODO https://github.com/zig-lang/zig/issues/733 var adapter = std.io.FileOutStream.init(&socket); var stream = &adapter.stream; @@ -210,9 +199,7 @@ test "listen on a port, send bytes, receive bytes" { const addr = std.net.Address.initIp4(ip4addr, 0); var loop = try Loop.init(std.debug.global_allocator); - var server = MyServer { - .tcp_server = try TcpServer.init(&loop), - }; + var server = MyServer{ .tcp_server = try TcpServer.init(&loop) }; defer server.tcp_server.deinit(); try server.tcp_server.listen(addr, MyServer.handler); diff --git a/std/hash/crc.zig b/std/hash/crc.zig index f88069ce3ce138d736f4c812a7fca3e57f5f5f3b..e4c1405a1c0ab6076a4e42d2556612ab0ed0e969 100644 --- a/std/hash/crc.zig +++ b/std/hash/crc.zig @@ -9,9 +9,9 @@ const std = @import("../index.zig"); const debug = std.debug; pub const Polynomial = struct { - const IEEE = 0xedb88320; + const IEEE = 0xedb88320; const Castagnoli = 0x82f63b78; - const Koopman = 0xeb31d82e; + const Koopman = 0xeb31d82e; }; // IEEE is by far the most common CRC and so is aliased by default. @@ -27,20 +27,22 @@ pub fn Crc32WithPoly(comptime poly: u32) type { for (tables[0]) |*e, i| { var crc = u32(i); - var j: usize = 0; while (j < 8) : (j += 1) { + var j: usize = 0; + while (j < 8) : (j += 1) { if (crc & 1 == 1) { crc = (crc >> 1) ^ poly; } else { crc = (crc >> 1); } } - *e = crc; + e.* = crc; } var i: usize = 0; while (i < 256) : (i += 1) { var crc = tables[0][i]; - var j: usize = 1; while (j < 8) : (j += 1) { + var j: usize = 1; + while (j < 8) : (j += 1) { const index = @truncate(u8, crc); crc = tables[0][index] ^ (crc >> 8); tables[j][i] = crc; @@ -53,22 +55,21 @@ pub fn Crc32WithPoly(comptime poly: u32) type { crc: u32, pub fn init() Self { - return Self { - .crc = 0xffffffff, - }; + return Self{ .crc = 0xffffffff }; } pub fn update(self: &Self, input: []const u8) void { var i: usize = 0; while (i + 8 <= input.len) : (i += 8) { - const p = input[i..i+8]; + const p = input[i..i + 8]; // Unrolling this way gives ~50Mb/s increase - self.crc ^= (u32(p[0]) << 0); - self.crc ^= (u32(p[1]) << 8); + self.crc ^= (u32(p[0]) << 0); + self.crc ^= (u32(p[1]) << 8); self.crc ^= (u32(p[2]) << 16); self.crc ^= (u32(p[3]) << 24); + self.crc = lookup_tables[0][p[7]] ^ lookup_tables[1][p[6]] ^ @@ -123,14 +124,15 @@ pub fn Crc32SmallWithPoly(comptime poly: u32) type { for (table) |*e, i| { var crc = u32(i * 16); - var j: usize = 0; while (j < 8) : (j += 1) { + var j: usize = 0; + while (j < 8) : (j += 1) { if (crc & 1 == 1) { crc = (crc >> 1) ^ poly; } else { crc = (crc >> 1); } } - *e = crc; + e.* = crc; } break :block table; @@ -139,9 +141,7 @@ pub fn Crc32SmallWithPoly(comptime poly: u32) type { crc: u32, pub fn init() Self { - return Self { - .crc = 0xffffffff, - }; + return Self{ .crc = 0xffffffff }; } pub fn update(self: &Self, input: []const u8) void { diff --git a/std/hash_map.zig b/std/hash_map.zig index 2a178d9d44de58f481afec52fe92d4f7d93d8708..e3b86f8a3bf59dc3ca3fe40c6f16e377818a8b5b 100644 --- a/std/hash_map.zig +++ b/std/hash_map.zig @@ -9,10 +9,7 @@ const builtin = @import("builtin"); const want_modification_safety = builtin.mode != builtin.Mode.ReleaseFast; const debug_u32 = if (want_modification_safety) u32 else void; -pub fn HashMap(comptime K: type, comptime V: type, - comptime hash: fn(key: K)u32, - comptime eql: fn(a: K, b: K)bool) type -{ +pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn(key: K) u32, comptime eql: fn(a: K, b: K) bool) type { return struct { entries: []Entry, size: usize, @@ -65,7 +62,7 @@ pub fn HashMap(comptime K: type, comptime V: type, }; pub fn init(allocator: &Allocator) Self { - return Self { + return Self{ .entries = []Entry{}, .allocator = allocator, .size = 0, @@ -129,34 +126,36 @@ pub fn HashMap(comptime K: type, comptime V: type, if (hm.entries.len == 0) return null; hm.incrementModificationCount(); const start_index = hm.keyToIndex(key); - {var roll_over: usize = 0; while (roll_over <= hm.max_distance_from_start_index) : (roll_over += 1) { - const index = (start_index + roll_over) % hm.entries.len; - var entry = &hm.entries[index]; + { + var roll_over: usize = 0; + while (roll_over <= hm.max_distance_from_start_index) : (roll_over += 1) { + const index = (start_index + roll_over) % hm.entries.len; + var entry = &hm.entries[index]; - if (!entry.used) - return null; + if (!entry.used) return null; - if (!eql(entry.key, key)) continue; + if (!eql(entry.key, key)) continue; - while (roll_over < hm.entries.len) : (roll_over += 1) { - const next_index = (start_index + roll_over + 1) % hm.entries.len; - const next_entry = &hm.entries[next_index]; - if (!next_entry.used or next_entry.distance_from_start_index == 0) { - entry.used = false; - hm.size -= 1; - return entry; + while (roll_over < hm.entries.len) : (roll_over += 1) { + const next_index = (start_index + roll_over + 1) % hm.entries.len; + const next_entry = &hm.entries[next_index]; + if (!next_entry.used or next_entry.distance_from_start_index == 0) { + entry.used = false; + hm.size -= 1; + return entry; + } + entry.* = next_entry.*; + entry.distance_from_start_index -= 1; + entry = next_entry; } - *entry = *next_entry; - entry.distance_from_start_index -= 1; - entry = next_entry; + unreachable; // shifting everything in the table } - unreachable; // shifting everything in the table - }} + } return null; } pub fn iterator(hm: &const Self) Iterator { - return Iterator { + return Iterator{ .hm = hm, .count = 0, .index = 0, @@ -182,21 +181,23 @@ pub fn HashMap(comptime K: type, comptime V: type, /// Returns the value that was already there. fn internalPut(hm: &Self, orig_key: K, orig_value: &const V) ?V { var key = orig_key; - var value = *orig_value; + var value = orig_value.*; const start_index = hm.keyToIndex(key); var roll_over: usize = 0; var distance_from_start_index: usize = 0; - while (roll_over < hm.entries.len) : ({roll_over += 1; distance_from_start_index += 1;}) { + while (roll_over < hm.entries.len) : ({ + roll_over += 1; + distance_from_start_index += 1; + }) { const index = (start_index + roll_over) % hm.entries.len; const entry = &hm.entries[index]; if (entry.used and !eql(entry.key, key)) { if (entry.distance_from_start_index < distance_from_start_index) { // robin hood to the rescue - const tmp = *entry; - hm.max_distance_from_start_index = math.max(hm.max_distance_from_start_index, - distance_from_start_index); - *entry = Entry { + const tmp = entry.*; + hm.max_distance_from_start_index = math.max(hm.max_distance_from_start_index, distance_from_start_index); + entry.* = Entry{ .used = true, .distance_from_start_index = distance_from_start_index, .key = key, @@ -219,7 +220,7 @@ pub fn HashMap(comptime K: type, comptime V: type, } hm.max_distance_from_start_index = math.max(distance_from_start_index, hm.max_distance_from_start_index); - *entry = Entry { + entry.* = Entry{ .used = true, .distance_from_start_index = distance_from_start_index, .key = key, @@ -232,13 +233,16 @@ pub fn HashMap(comptime K: type, comptime V: type, fn internalGet(hm: &const Self, key: K) ?&Entry { const start_index = hm.keyToIndex(key); - {var roll_over: usize = 0; while (roll_over <= hm.max_distance_from_start_index) : (roll_over += 1) { - const index = (start_index + roll_over) % hm.entries.len; - const entry = &hm.entries[index]; + { + var roll_over: usize = 0; + while (roll_over <= hm.max_distance_from_start_index) : (roll_over += 1) { + const index = (start_index + roll_over) % hm.entries.len; + const entry = &hm.entries[index]; - if (!entry.used) return null; - if (eql(entry.key, key)) return entry; - }} + if (!entry.used) return null; + if (eql(entry.key, key)) return entry; + } + } return null; } @@ -282,11 +286,19 @@ test "iterator hash map" { assert((reset_map.put(2, 22) catch unreachable) == null); assert((reset_map.put(3, 33) catch unreachable) == null); - var keys = []i32 { 1, 2, 3 }; - var values = []i32 { 11, 22, 33 }; + var keys = []i32{ + 1, + 2, + 3, + }; + var values = []i32{ + 11, + 22, + 33, + }; var it = reset_map.iterator(); - var count : usize = 0; + var count: usize = 0; while (it.next()) |next| { assert(next.key == keys[count]); assert(next.value == values[count]); @@ -305,7 +317,7 @@ test "iterator hash map" { } it.reset(); - var entry = ?? it.next(); + var entry = ??it.next(); assert(entry.key == keys[0]); assert(entry.value == values[0]); } diff --git a/std/json.zig b/std/json.zig index 6f853501ed41679415b670863d2800e5cdb943d0..2ea9083e2f96749e9ca19cd1ddb7849f6b63eca1 100644 --- a/std/json.zig +++ b/std/json.zig @@ -35,7 +35,7 @@ pub const Token = struct { }; pub fn init(id: Id, count: usize, offset: u1) Token { - return Token { + return Token{ .id = id, .offset = offset, .string_has_escape = false, @@ -45,7 +45,7 @@ pub const Token = struct { } pub fn initString(count: usize, has_unicode_escape: bool) Token { - return Token { + return Token{ .id = Id.String, .offset = 0, .string_has_escape = has_unicode_escape, @@ -55,7 +55,7 @@ pub const Token = struct { } pub fn initNumber(count: usize, number_is_integer: bool) Token { - return Token { + return Token{ .id = Id.Number, .offset = 0, .string_has_escape = false, @@ -66,7 +66,7 @@ pub const Token = struct { // A marker token is a zero-length pub fn initMarker(id: Id) Token { - return Token { + return Token{ .id = id, .offset = 0, .string_has_escape = false, @@ -77,7 +77,7 @@ pub const Token = struct { // Slice into the underlying input string. pub fn slice(self: &const Token, input: []const u8, i: usize) []const u8 { - return input[i + self.offset - self.count .. i + self.offset]; + return input[i + self.offset - self.count..i + self.offset]; } }; @@ -105,8 +105,8 @@ const StreamingJsonParser = struct { stack: u256, stack_used: u8, - const object_bit = 0; - const array_bit = 1; + const object_bit = 0; + const array_bit = 1; const max_stack_size = @maxValue(u8); pub fn init() StreamingJsonParser { @@ -120,7 +120,7 @@ const StreamingJsonParser = struct { p.count = 0; // Set before ever read in main transition function p.after_string_state = undefined; - p.after_value_state = State.ValueEnd; // handle end of values normally + p.after_value_state = State.ValueEnd; // handle end of values normally p.stack = 0; p.stack_used = 0; p.complete = false; @@ -181,7 +181,7 @@ const StreamingJsonParser = struct { } }; - pub const Error = error { + pub const Error = error{ InvalidTopLevel, TooManyNestedItems, TooManyClosingItems, @@ -206,8 +206,8 @@ const StreamingJsonParser = struct { // // There is currently no error recovery on a bad stream. pub fn feed(p: &StreamingJsonParser, c: u8, token1: &?Token, token2: &?Token) Error!void { - *token1 = null; - *token2 = null; + token1.* = null; + token2.* = null; p.count += 1; // unlikely @@ -228,7 +228,7 @@ const StreamingJsonParser = struct { p.state = State.ValueBegin; p.after_string_state = State.ObjectSeparator; - *token = Token.initMarker(Token.Id.ObjectBegin); + token.* = Token.initMarker(Token.Id.ObjectBegin); }, '[' => { p.stack <<= 1; @@ -238,7 +238,7 @@ const StreamingJsonParser = struct { p.state = State.ValueBegin; p.after_string_state = State.ValueEnd; - *token = Token.initMarker(Token.Id.ArrayBegin); + token.* = Token.initMarker(Token.Id.ArrayBegin); }, '-' => { p.number_is_integer = true; @@ -281,7 +281,10 @@ const StreamingJsonParser = struct { p.after_value_state = State.TopLevelEnd; p.count = 0; }, - 0x09, 0x0A, 0x0D, 0x20 => { + 0x09, + 0x0A, + 0x0D, + 0x20 => { // whitespace }, else => { @@ -290,7 +293,10 @@ const StreamingJsonParser = struct { }, State.TopLevelEnd => switch (c) { - 0x09, 0x0A, 0x0D, 0x20 => { + 0x09, + 0x0A, + 0x0D, + 0x20 => { // whitespace }, else => { @@ -324,7 +330,7 @@ const StreamingJsonParser = struct { else => {}, } - *token = Token.initMarker(Token.Id.ObjectEnd); + token.* = Token.initMarker(Token.Id.ObjectEnd); }, ']' => { if (p.stack & 1 != array_bit) { @@ -348,7 +354,7 @@ const StreamingJsonParser = struct { else => {}, } - *token = Token.initMarker(Token.Id.ArrayEnd); + token.* = Token.initMarker(Token.Id.ArrayEnd); }, '{' => { if (p.stack_used == max_stack_size) { @@ -362,7 +368,7 @@ const StreamingJsonParser = struct { p.state = State.ValueBegin; p.after_string_state = State.ObjectSeparator; - *token = Token.initMarker(Token.Id.ObjectBegin); + token.* = Token.initMarker(Token.Id.ObjectBegin); }, '[' => { if (p.stack_used == max_stack_size) { @@ -376,7 +382,7 @@ const StreamingJsonParser = struct { p.state = State.ValueBegin; p.after_string_state = State.ValueEnd; - *token = Token.initMarker(Token.Id.ArrayBegin); + token.* = Token.initMarker(Token.Id.ArrayBegin); }, '-' => { p.state = State.Number; @@ -406,7 +412,10 @@ const StreamingJsonParser = struct { p.state = State.NullLiteral1; p.count = 0; }, - 0x09, 0x0A, 0x0D, 0x20 => { + 0x09, + 0x0A, + 0x0D, + 0x20 => { // whitespace }, else => { @@ -428,7 +437,7 @@ const StreamingJsonParser = struct { p.state = State.ValueBegin; p.after_string_state = State.ObjectSeparator; - *token = Token.initMarker(Token.Id.ObjectBegin); + token.* = Token.initMarker(Token.Id.ObjectBegin); }, '[' => { if (p.stack_used == max_stack_size) { @@ -442,7 +451,7 @@ const StreamingJsonParser = struct { p.state = State.ValueBegin; p.after_string_state = State.ValueEnd; - *token = Token.initMarker(Token.Id.ArrayBegin); + token.* = Token.initMarker(Token.Id.ArrayBegin); }, '-' => { p.state = State.Number; @@ -472,7 +481,10 @@ const StreamingJsonParser = struct { p.state = State.NullLiteral1; p.count = 0; }, - 0x09, 0x0A, 0x0D, 0x20 => { + 0x09, + 0x0A, + 0x0D, + 0x20 => { // whitespace }, else => { @@ -501,7 +513,7 @@ const StreamingJsonParser = struct { p.state = State.TopLevelEnd; } - *token = Token.initMarker(Token.Id.ArrayEnd); + token.* = Token.initMarker(Token.Id.ArrayEnd); }, '}' => { if (p.stack_used == 0) { @@ -519,9 +531,12 @@ const StreamingJsonParser = struct { p.state = State.TopLevelEnd; } - *token = Token.initMarker(Token.Id.ObjectEnd); + token.* = Token.initMarker(Token.Id.ObjectEnd); }, - 0x09, 0x0A, 0x0D, 0x20 => { + 0x09, + 0x0A, + 0x0D, + 0x20 => { // whitespace }, else => { @@ -534,7 +549,10 @@ const StreamingJsonParser = struct { p.state = State.ValueBegin; p.after_string_state = State.ValueEnd; }, - 0x09, 0x0A, 0x0D, 0x20 => { + 0x09, + 0x0A, + 0x0D, + 0x20 => { // whitespace }, else => { @@ -553,12 +571,15 @@ const StreamingJsonParser = struct { p.complete = true; } - *token = Token.initString(p.count - 1, p.string_has_escape); + token.* = Token.initString(p.count - 1, p.string_has_escape); }, '\\' => { p.state = State.StringEscapeCharacter; }, - 0x20, 0x21, 0x23 ... 0x5B, 0x5D ... 0x7F => { + 0x20, + 0x21, + 0x23 ... 0x5B, + 0x5D ... 0x7F => { // non-control ascii }, 0xC0 ... 0xDF => { @@ -599,7 +620,14 @@ const StreamingJsonParser = struct { // The current JSONTestSuite tests rely on both of this behaviour being present // however, so we default to the status quo where both are accepted until this // is further clarified. - '"', '\\', '/', 'b', 'f', 'n', 'r', 't' => { + '"', + '\\', + '/', + 'b', + 'f', + 'n', + 'r', + 't' => { p.string_has_escape = true; p.state = State.String; }, @@ -613,28 +641,36 @@ const StreamingJsonParser = struct { }, State.StringEscapeHexUnicode4 => switch (c) { - '0' ... '9', 'A' ... 'F', 'a' ... 'f' => { + '0' ... '9', + 'A' ... 'F', + 'a' ... 'f' => { p.state = State.StringEscapeHexUnicode3; }, else => return error.InvalidUnicodeHexSymbol, }, State.StringEscapeHexUnicode3 => switch (c) { - '0' ... '9', 'A' ... 'F', 'a' ... 'f' => { + '0' ... '9', + 'A' ... 'F', + 'a' ... 'f' => { p.state = State.StringEscapeHexUnicode2; }, else => return error.InvalidUnicodeHexSymbol, }, State.StringEscapeHexUnicode2 => switch (c) { - '0' ... '9', 'A' ... 'F', 'a' ... 'f' => { + '0' ... '9', + 'A' ... 'F', + 'a' ... 'f' => { p.state = State.StringEscapeHexUnicode1; }, else => return error.InvalidUnicodeHexSymbol, }, State.StringEscapeHexUnicode1 => switch (c) { - '0' ... '9', 'A' ... 'F', 'a' ... 'f' => { + '0' ... '9', + 'A' ... 'F', + 'a' ... 'f' => { p.state = State.String; }, else => return error.InvalidUnicodeHexSymbol, @@ -662,13 +698,14 @@ const StreamingJsonParser = struct { p.number_is_integer = false; p.state = State.NumberFractionalRequired; }, - 'e', 'E' => { + 'e', + 'E' => { p.number_is_integer = false; p.state = State.NumberExponent; }, else => { p.state = p.after_value_state; - *token = Token.initNumber(p.count, p.number_is_integer); + token.* = Token.initNumber(p.count, p.number_is_integer); return true; }, } @@ -681,7 +718,8 @@ const StreamingJsonParser = struct { p.number_is_integer = false; p.state = State.NumberFractionalRequired; }, - 'e', 'E' => { + 'e', + 'E' => { p.number_is_integer = false; p.state = State.NumberExponent; }, @@ -690,7 +728,7 @@ const StreamingJsonParser = struct { }, else => { p.state = p.after_value_state; - *token = Token.initNumber(p.count, p.number_is_integer); + token.* = Token.initNumber(p.count, p.number_is_integer); return true; }, } @@ -714,13 +752,14 @@ const StreamingJsonParser = struct { '0' ... '9' => { // another digit }, - 'e', 'E' => { + 'e', + 'E' => { p.number_is_integer = false; p.state = State.NumberExponent; }, else => { p.state = p.after_value_state; - *token = Token.initNumber(p.count, p.number_is_integer); + token.* = Token.initNumber(p.count, p.number_is_integer); return true; }, } @@ -729,20 +768,22 @@ const StreamingJsonParser = struct { State.NumberMaybeExponent => { p.complete = p.after_value_state == State.TopLevelEnd; switch (c) { - 'e', 'E' => { + 'e', + 'E' => { p.number_is_integer = false; p.state = State.NumberExponent; }, else => { p.state = p.after_value_state; - *token = Token.initNumber(p.count, p.number_is_integer); + token.* = Token.initNumber(p.count, p.number_is_integer); return true; }, } }, State.NumberExponent => switch (c) { - '-', '+', => { + '-', + '+' => { p.complete = false; p.state = State.NumberExponentDigitsRequired; }, @@ -773,7 +814,7 @@ const StreamingJsonParser = struct { }, else => { p.state = p.after_value_state; - *token = Token.initNumber(p.count, p.number_is_integer); + token.* = Token.initNumber(p.count, p.number_is_integer); return true; }, } @@ -793,7 +834,7 @@ const StreamingJsonParser = struct { 'e' => { p.state = p.after_value_state; p.complete = p.state == State.TopLevelEnd; - *token = Token.init(Token.Id.True, p.count + 1, 1); + token.* = Token.init(Token.Id.True, p.count + 1, 1); }, else => { return error.InvalidLiteral; @@ -819,7 +860,7 @@ const StreamingJsonParser = struct { 'e' => { p.state = p.after_value_state; p.complete = p.state == State.TopLevelEnd; - *token = Token.init(Token.Id.False, p.count + 1, 1); + token.* = Token.init(Token.Id.False, p.count + 1, 1); }, else => { return error.InvalidLiteral; @@ -840,7 +881,7 @@ const StreamingJsonParser = struct { 'l' => { p.state = p.after_value_state; p.complete = p.state == State.TopLevelEnd; - *token = Token.init(Token.Id.Null, p.count + 1, 1); + token.* = Token.init(Token.Id.Null, p.count + 1, 1); }, else => { return error.InvalidLiteral; @@ -895,7 +936,7 @@ pub const Value = union(enum) { Object: ObjectMap, pub fn dump(self: &const Value) void { - switch (*self) { + switch (self.*) { Value.Null => { std.debug.warn("null"); }, @@ -950,7 +991,7 @@ pub const Value = union(enum) { } fn dumpIndentLevel(self: &const Value, indent: usize, level: usize) void { - switch (*self) { + switch (self.*) { Value.Null => { std.debug.warn("null"); }, @@ -1027,7 +1068,7 @@ const JsonParser = struct { }; pub fn init(allocator: &Allocator, copy_strings: bool) JsonParser { - return JsonParser { + return JsonParser{ .allocator = allocator, .state = State.Simple, .copy_strings = copy_strings, @@ -1082,7 +1123,7 @@ const JsonParser = struct { std.debug.assert(p.stack.len == 1); - return ValueTree { + return ValueTree{ .arena = arena, .root = p.stack.at(0), }; @@ -1115,11 +1156,11 @@ const JsonParser = struct { switch (token.id) { Token.Id.ObjectBegin => { - try p.stack.append(Value { .Object = ObjectMap.init(allocator) }); + try p.stack.append(Value{ .Object = ObjectMap.init(allocator) }); p.state = State.ObjectKey; }, Token.Id.ArrayBegin => { - try p.stack.append(Value { .Array = ArrayList(Value).init(allocator) }); + try p.stack.append(Value{ .Array = ArrayList(Value).init(allocator) }); p.state = State.ArrayValue; }, Token.Id.String => { @@ -1133,12 +1174,12 @@ const JsonParser = struct { p.state = State.ObjectKey; }, Token.Id.True => { - _ = try object.put(key, Value { .Bool = true }); + _ = try object.put(key, Value{ .Bool = true }); _ = p.stack.pop(); p.state = State.ObjectKey; }, Token.Id.False => { - _ = try object.put(key, Value { .Bool = false }); + _ = try object.put(key, Value{ .Bool = false }); _ = p.stack.pop(); p.state = State.ObjectKey; }, @@ -1165,11 +1206,11 @@ const JsonParser = struct { try p.pushToParent(value); }, Token.Id.ObjectBegin => { - try p.stack.append(Value { .Object = ObjectMap.init(allocator) }); + try p.stack.append(Value{ .Object = ObjectMap.init(allocator) }); p.state = State.ObjectKey; }, Token.Id.ArrayBegin => { - try p.stack.append(Value { .Array = ArrayList(Value).init(allocator) }); + try p.stack.append(Value{ .Array = ArrayList(Value).init(allocator) }); p.state = State.ArrayValue; }, Token.Id.String => { @@ -1179,10 +1220,10 @@ const JsonParser = struct { try array.append(try p.parseNumber(token, input, i)); }, Token.Id.True => { - try array.append(Value { .Bool = true }); + try array.append(Value{ .Bool = true }); }, Token.Id.False => { - try array.append(Value { .Bool = false }); + try array.append(Value{ .Bool = false }); }, Token.Id.Null => { try array.append(Value.Null); @@ -1194,11 +1235,11 @@ const JsonParser = struct { }, State.Simple => switch (token.id) { Token.Id.ObjectBegin => { - try p.stack.append(Value { .Object = ObjectMap.init(allocator) }); + try p.stack.append(Value{ .Object = ObjectMap.init(allocator) }); p.state = State.ObjectKey; }, Token.Id.ArrayBegin => { - try p.stack.append(Value { .Array = ArrayList(Value).init(allocator) }); + try p.stack.append(Value{ .Array = ArrayList(Value).init(allocator) }); p.state = State.ArrayValue; }, Token.Id.String => { @@ -1208,15 +1249,16 @@ const JsonParser = struct { try p.stack.append(try p.parseNumber(token, input, i)); }, Token.Id.True => { - try p.stack.append(Value { .Bool = true }); + try p.stack.append(Value{ .Bool = true }); }, Token.Id.False => { - try p.stack.append(Value { .Bool = false }); + try p.stack.append(Value{ .Bool = false }); }, Token.Id.Null => { try p.stack.append(Value.Null); }, - Token.Id.ObjectEnd, Token.Id.ArrayEnd => { + Token.Id.ObjectEnd, + Token.Id.ArrayEnd => { unreachable; }, }, @@ -1248,15 +1290,14 @@ const JsonParser = struct { // TODO: We don't strictly have to copy values which do not contain any escape // characters if flagged with the option. const slice = token.slice(input, i); - return Value { .String = try mem.dupe(p.allocator, u8, slice) }; + return Value{ .String = try mem.dupe(p.allocator, u8, slice) }; } fn parseNumber(p: &JsonParser, token: &const Token, input: []const u8, i: usize) !Value { return if (token.number_is_integer) - Value { .Integer = try std.fmt.parseInt(i64, token.slice(input, i), 10) } + Value{ .Integer = try std.fmt.parseInt(i64, token.slice(input, i), 10) } else - @panic("TODO: fmt.parseFloat not yet implemented") - ; + @panic("TODO: fmt.parseFloat not yet implemented"); } }; @@ -1267,21 +1308,21 @@ test "json parser dynamic" { defer p.deinit(); const s = - \\{ - \\ "Image": { - \\ "Width": 800, - \\ "Height": 600, - \\ "Title": "View from 15th Floor", - \\ "Thumbnail": { - \\ "Url": "http://www.example.com/image/481989943", - \\ "Height": 125, - \\ "Width": 100 - \\ }, - \\ "Animated" : false, - \\ "IDs": [116, 943, 234, 38793] - \\ } - \\} - ; + \\{ + \\ "Image": { + \\ "Width": 800, + \\ "Height": 600, + \\ "Title": "View from 15th Floor", + \\ "Thumbnail": { + \\ "Url": "http://www.example.com/image/481989943", + \\ "Height": 125, + \\ "Width": 100 + \\ }, + \\ "Animated" : false, + \\ "IDs": [116, 943, 234, 38793] + \\ } + \\} + ; var tree = try p.parse(s); defer tree.deinit(); diff --git a/std/math/acos.zig b/std/math/acos.zig index a4f08af30679b85977772ae3906b4dc2be7a76e4..284f73fc9150ddf3476dbde4112d9c4ec490494a 100644 --- a/std/math/acos.zig +++ b/std/math/acos.zig @@ -16,7 +16,7 @@ pub fn acos(x: var) @typeOf(x) { } fn r32(z: f32) f32 { - const pS0 = 1.6666586697e-01; + const pS0 = 1.6666586697e-01; const pS1 = -4.2743422091e-02; const pS2 = -8.6563630030e-03; const qS1 = -7.0662963390e-01; @@ -74,16 +74,16 @@ fn acos32(x: f32) f32 { } fn r64(z: f64) f64 { - const pS0: f64 = 1.66666666666666657415e-01; + const pS0: f64 = 1.66666666666666657415e-01; const pS1: f64 = -3.25565818622400915405e-01; - const pS2: f64 = 2.01212532134862925881e-01; + const pS2: f64 = 2.01212532134862925881e-01; const pS3: f64 = -4.00555345006794114027e-02; - const pS4: f64 = 7.91534994289814532176e-04; - const pS5: f64 = 3.47933107596021167570e-05; + const pS4: f64 = 7.91534994289814532176e-04; + const pS5: f64 = 3.47933107596021167570e-05; const qS1: f64 = -2.40339491173441421878e+00; - const qS2: f64 = 2.02094576023350569471e+00; + const qS2: f64 = 2.02094576023350569471e+00; const qS3: f64 = -6.88283971605453293030e-01; - const qS4: f64 = 7.70381505559019352791e-02; + const qS4: f64 = 7.70381505559019352791e-02; const p = z * (pS0 + z * (pS1 + z * (pS2 + z * (pS3 + z * (pS4 + z * pS5))))); const q = 1.0 + z * (qS1 + z * (qS2 + z * (qS3 + z * qS4))); diff --git a/std/math/asin.zig b/std/math/asin.zig index 9fa5a80ea508a731d114ff940186a1a77f15495c..2ee3aa6048f13e37d0d3045bc09f9d9308852b48 100644 --- a/std/math/asin.zig +++ b/std/math/asin.zig @@ -17,7 +17,7 @@ pub fn asin(x: var) @typeOf(x) { } fn r32(z: f32) f32 { - const pS0 = 1.6666586697e-01; + const pS0 = 1.6666586697e-01; const pS1 = -4.2743422091e-02; const pS2 = -8.6563630030e-03; const qS1 = -7.0662963390e-01; @@ -37,9 +37,9 @@ fn asin32(x: f32) f32 { if (ix >= 0x3F800000) { // |x| >= 1 if (ix == 0x3F800000) { - return x * pio2 + 0x1.0p-120; // asin(+-1) = +-pi/2 with inexact + return x * pio2 + 0x1.0p-120; // asin(+-1) = +-pi/2 with inexact } else { - return math.nan(f32); // asin(|x| > 1) is nan + return math.nan(f32); // asin(|x| > 1) is nan } } @@ -66,16 +66,16 @@ fn asin32(x: f32) f32 { } fn r64(z: f64) f64 { - const pS0: f64 = 1.66666666666666657415e-01; + const pS0: f64 = 1.66666666666666657415e-01; const pS1: f64 = -3.25565818622400915405e-01; - const pS2: f64 = 2.01212532134862925881e-01; + const pS2: f64 = 2.01212532134862925881e-01; const pS3: f64 = -4.00555345006794114027e-02; - const pS4: f64 = 7.91534994289814532176e-04; - const pS5: f64 = 3.47933107596021167570e-05; + const pS4: f64 = 7.91534994289814532176e-04; + const pS5: f64 = 3.47933107596021167570e-05; const qS1: f64 = -2.40339491173441421878e+00; - const qS2: f64 = 2.02094576023350569471e+00; + const qS2: f64 = 2.02094576023350569471e+00; const qS3: f64 = -6.88283971605453293030e-01; - const qS4: f64 = 7.70381505559019352791e-02; + const qS4: f64 = 7.70381505559019352791e-02; const p = z * (pS0 + z * (pS1 + z * (pS2 + z * (pS3 + z * (pS4 + z * pS5))))); const q = 1.0 + z * (qS1 + z * (qS2 + z * (qS3 + z * qS4))); diff --git a/std/math/atan2.zig b/std/math/atan2.zig index 37c520da468035b66a1fae63d7b148c31beb8017..0892f0b438b86070f184cfeab7a8fe259f0f3c4f 100644 --- a/std/math/atan2.zig +++ b/std/math/atan2.zig @@ -31,7 +31,7 @@ pub fn atan2(comptime T: type, x: T, y: T) T { } fn atan2_32(y: f32, x: f32) f32 { - const pi: f32 = 3.1415927410e+00; + const pi: f32 = 3.1415927410e+00; const pi_lo: f32 = -8.7422776573e-08; if (math.isNan(x) or math.isNan(y)) { @@ -53,9 +53,10 @@ fn atan2_32(y: f32, x: f32) f32 { if (iy == 0) { switch (m) { - 0, 1 => return y, // atan(+-0, +...) - 2 => return pi, // atan(+0, -...) - 3 => return -pi, // atan(-0, -...) + 0, + 1 => return y, // atan(+-0, +...) + 2 => return pi, // atan(+0, -...) + 3 => return -pi, // atan(-0, -...) else => unreachable, } } @@ -71,18 +72,18 @@ fn atan2_32(y: f32, x: f32) f32 { if (ix == 0x7F800000) { if (iy == 0x7F800000) { switch (m) { - 0 => return pi / 4, // atan(+inf, +inf) - 1 => return -pi / 4, // atan(-inf, +inf) - 2 => return 3*pi / 4, // atan(+inf, -inf) - 3 => return -3*pi / 4, // atan(-inf, -inf) + 0 => return pi / 4, // atan(+inf, +inf) + 1 => return -pi / 4, // atan(-inf, +inf) + 2 => return 3 * pi / 4, // atan(+inf, -inf) + 3 => return -3 * pi / 4, // atan(-inf, -inf) else => unreachable, } } else { switch (m) { - 0 => return 0.0, // atan(+..., +inf) - 1 => return -0.0, // atan(-..., +inf) - 2 => return pi, // atan(+..., -inf) - 3 => return -pi, // atan(-...f, -inf) + 0 => return 0.0, // atan(+..., +inf) + 1 => return -0.0, // atan(-..., +inf) + 2 => return pi, // atan(+..., -inf) + 3 => return -pi, // atan(-...f, -inf) else => unreachable, } } @@ -107,16 +108,16 @@ fn atan2_32(y: f32, x: f32) f32 { }; switch (m) { - 0 => return z, // atan(+, +) - 1 => return -z, // atan(-, +) - 2 => return pi - (z - pi_lo), // atan(+, -) - 3 => return (z - pi_lo) - pi, // atan(-, -) + 0 => return z, // atan(+, +) + 1 => return -z, // atan(-, +) + 2 => return pi - (z - pi_lo), // atan(+, -) + 3 => return (z - pi_lo) - pi, // atan(-, -) else => unreachable, } } fn atan2_64(y: f64, x: f64) f64 { - const pi: f64 = 3.1415926535897931160E+00; + const pi: f64 = 3.1415926535897931160E+00; const pi_lo: f64 = 1.2246467991473531772E-16; if (math.isNan(x) or math.isNan(y)) { @@ -143,9 +144,10 @@ fn atan2_64(y: f64, x: f64) f64 { if (iy | ly == 0) { switch (m) { - 0, 1 => return y, // atan(+-0, +...) - 2 => return pi, // atan(+0, -...) - 3 => return -pi, // atan(-0, -...) + 0, + 1 => return y, // atan(+-0, +...) + 2 => return pi, // atan(+0, -...) + 3 => return -pi, // atan(-0, -...) else => unreachable, } } @@ -161,18 +163,18 @@ fn atan2_64(y: f64, x: f64) f64 { if (ix == 0x7FF00000) { if (iy == 0x7FF00000) { switch (m) { - 0 => return pi / 4, // atan(+inf, +inf) - 1 => return -pi / 4, // atan(-inf, +inf) - 2 => return 3*pi / 4, // atan(+inf, -inf) - 3 => return -3*pi / 4, // atan(-inf, -inf) + 0 => return pi / 4, // atan(+inf, +inf) + 1 => return -pi / 4, // atan(-inf, +inf) + 2 => return 3 * pi / 4, // atan(+inf, -inf) + 3 => return -3 * pi / 4, // atan(-inf, -inf) else => unreachable, } } else { switch (m) { - 0 => return 0.0, // atan(+..., +inf) - 1 => return -0.0, // atan(-..., +inf) - 2 => return pi, // atan(+..., -inf) - 3 => return -pi, // atan(-...f, -inf) + 0 => return 0.0, // atan(+..., +inf) + 1 => return -0.0, // atan(-..., +inf) + 2 => return pi, // atan(+..., -inf) + 3 => return -pi, // atan(-...f, -inf) else => unreachable, } } @@ -197,10 +199,10 @@ fn atan2_64(y: f64, x: f64) f64 { }; switch (m) { - 0 => return z, // atan(+, +) - 1 => return -z, // atan(-, +) - 2 => return pi - (z - pi_lo), // atan(+, -) - 3 => return (z - pi_lo) - pi, // atan(-, -) + 0 => return z, // atan(+, +) + 1 => return -z, // atan(-, +) + 2 => return pi - (z - pi_lo), // atan(+, -) + 3 => return (z - pi_lo) - pi, // atan(-, -) else => unreachable, } } diff --git a/std/math/cbrt.zig b/std/math/cbrt.zig index a265392ff70b26dfaeddb407c5f6e55e50f7e736..cd3b71ca8a593ee2a5c9599fc7e1dddcbbcb1165 100644 --- a/std/math/cbrt.zig +++ b/std/math/cbrt.zig @@ -58,15 +58,15 @@ fn cbrt32(x: f32) f32 { } fn cbrt64(x: f64) f64 { - const B1: u32 = 715094163; // (1023 - 1023 / 3 - 0.03306235651 * 2^20 - const B2: u32 = 696219795; // (1023 - 1023 / 3 - 54 / 3 - 0.03306235651 * 2^20 + const B1: u32 = 715094163; // (1023 - 1023 / 3 - 0.03306235651 * 2^20 + const B2: u32 = 696219795; // (1023 - 1023 / 3 - 54 / 3 - 0.03306235651 * 2^20 // |1 / cbrt(x) - p(x)| < 2^(23.5) - const P0: f64 = 1.87595182427177009643; + const P0: f64 = 1.87595182427177009643; const P1: f64 = -1.88497979543377169875; - const P2: f64 = 1.621429720105354466140; + const P2: f64 = 1.621429720105354466140; const P3: f64 = -0.758397934778766047437; - const P4: f64 = 0.145996192886612446982; + const P4: f64 = 0.145996192886612446982; var u = @bitCast(u64, x); var hx = u32(u >> 32) & 0x7FFFFFFF; diff --git a/std/math/ceil.zig b/std/math/ceil.zig index 5bdb84ca00907f363285ea7dc97eb7ed5b406c9d..a189bb66d2aa1d1dda3c332054d79c98b165012c 100644 --- a/std/math/ceil.zig +++ b/std/math/ceil.zig @@ -56,7 +56,7 @@ fn ceil64(x: f64) f64 { const e = (u >> 52) & 0x7FF; var y: f64 = undefined; - if (e >= 0x3FF+52 or x == 0) { + if (e >= 0x3FF + 52 or x == 0) { return x; } @@ -68,7 +68,7 @@ fn ceil64(x: f64) f64 { y = x + math.f64_toint - math.f64_toint - x; } - if (e <= 0x3FF-1) { + if (e <= 0x3FF - 1) { math.forceEval(y); if (u >> 63 != 0) { return -0.0; diff --git a/std/math/cos.zig b/std/math/cos.zig index bb405b0d10517d442831ac26c20521c068bd018a..5e5ec4f1cb6c72579c7c28af0b1eb7b886e9f049 100644 --- a/std/math/cos.zig +++ b/std/math/cos.zig @@ -18,20 +18,20 @@ pub fn cos(x: var) @typeOf(x) { } // sin polynomial coefficients -const S0 = 1.58962301576546568060E-10; +const S0 = 1.58962301576546568060E-10; const S1 = -2.50507477628578072866E-8; -const S2 = 2.75573136213857245213E-6; +const S2 = 2.75573136213857245213E-6; const S3 = -1.98412698295895385996E-4; -const S4 = 8.33333333332211858878E-3; +const S4 = 8.33333333332211858878E-3; const S5 = -1.66666666666666307295E-1; // cos polynomial coeffiecients const C0 = -1.13585365213876817300E-11; -const C1 = 2.08757008419747316778E-9; +const C1 = 2.08757008419747316778E-9; const C2 = -2.75573141792967388112E-7; -const C3 = 2.48015872888517045348E-5; +const C3 = 2.48015872888517045348E-5; const C4 = -1.38888888888730564116E-3; -const C5 = 4.16666666666665929218E-2; +const C5 = 4.16666666666665929218E-2; // NOTE: This is taken from the go stdlib. The musl implementation is much more complex. // diff --git a/std/math/floor.zig b/std/math/floor.zig index 1b8e2dfeedb1483f4fc29ec234b5f0893e08460d..7d5364787f7dd45b678802147c3ab976f4b6b3d5 100644 --- a/std/math/floor.zig +++ b/std/math/floor.zig @@ -57,7 +57,7 @@ fn floor64(x: f64) f64 { const e = (u >> 52) & 0x7FF; var y: f64 = undefined; - if (e >= 0x3FF+52 or x == 0) { + if (e >= 0x3FF + 52 or x == 0) { return x; } @@ -69,7 +69,7 @@ fn floor64(x: f64) f64 { y = x + math.f64_toint - math.f64_toint - x; } - if (e <= 0x3FF-1) { + if (e <= 0x3FF - 1) { math.forceEval(y); if (u >> 63 != 0) { return -1.0; diff --git a/std/math/fma.zig b/std/math/fma.zig index e8d146db34a047fde519bb5917cc9169b37589f2..3e9214f35b1b5ee7b84d28e882b63cb11a0d3520 100644 --- a/std/math/fma.zig +++ b/std/math/fma.zig @@ -5,7 +5,7 @@ const assert = std.debug.assert; pub fn fma(comptime T: type, x: T, y: T, z: T) T { return switch (T) { f32 => fma32(x, y, z), - f64 => fma64(x, y ,z), + f64 => fma64(x, y, z), else => @compileError("fma not implemented for " ++ @typeName(T)), }; } @@ -71,7 +71,10 @@ fn fma64(x: f64, y: f64, z: f64) f64 { } } -const dd = struct { hi: f64, lo: f64, }; +const dd = struct { + hi: f64, + lo: f64, +}; fn dd_add(a: f64, b: f64) dd { var ret: dd = undefined; diff --git a/std/math/hypot.zig b/std/math/hypot.zig index 06427d0865c275eaa457f65f6b54ea28b8a01200..fe0de3a1ead05f55c83331e259fdc4926c661fcd 100644 --- a/std/math/hypot.zig +++ b/std/math/hypot.zig @@ -39,11 +39,11 @@ fn hypot32(x: f32, y: f32) f32 { } var z: f32 = 1.0; - if (ux >= (0x7F+60) << 23) { + if (ux >= (0x7F + 60) << 23) { z = 0x1.0p90; xx *= 0x1.0p-90; yy *= 0x1.0p-90; - } else if (uy < (0x7F-60) << 23) { + } else if (uy < (0x7F - 60) << 23) { z = 0x1.0p-90; xx *= 0x1.0p-90; yy *= 0x1.0p-90; @@ -57,8 +57,8 @@ fn sq(hi: &f64, lo: &f64, x: f64) void { const xc = x * split; const xh = x - xc + xc; const xl = x - xh; - *hi = x * x; - *lo = xh * xh - *hi + 2 * xh * xl + xl * xl; + hi.* = x * x; + lo.* = xh * xh - hi.* + 2 * xh * xl + xl * xl; } fn hypot64(x: f64, y: f64) f64 { diff --git a/std/math/ln.zig b/std/math/ln.zig index d09494b9982dec76f2cf78943c60d9d3108ca6b2..263e5955cb05ac126ac41a8e82128a3d0c2d4f7c 100644 --- a/std/math/ln.zig +++ b/std/math/ln.zig @@ -120,11 +120,9 @@ pub fn ln_64(x_: f64) f64 { k -= 54; x *= 0x1.0p54; hx = u32(@bitCast(u64, ix) >> 32); - } - else if (hx >= 0x7FF00000) { + } else if (hx >= 0x7FF00000) { return x; - } - else if (hx == 0x3FF00000 and ix << 32 == 0) { + } else if (hx == 0x3FF00000 and ix << 32 == 0) { return 0; } diff --git a/std/math/log10.zig b/std/math/log10.zig index aa74caa90119c714d5878d079793e76950a706bd..d9fa1dcb0263572e217b18a54e3f7bcc4376d1df 100644 --- a/std/math/log10.zig +++ b/std/math/log10.zig @@ -35,10 +35,10 @@ pub fn log10(x: var) @typeOf(x) { } pub fn log10_32(x_: f32) f32 { - const ivln10hi: f32 = 4.3432617188e-01; - const ivln10lo: f32 = -3.1689971365e-05; - const log10_2hi: f32 = 3.0102920532e-01; - const log10_2lo: f32 = 7.9034151668e-07; + const ivln10hi: f32 = 4.3432617188e-01; + const ivln10lo: f32 = -3.1689971365e-05; + const log10_2hi: f32 = 3.0102920532e-01; + const log10_2lo: f32 = 7.9034151668e-07; const Lg1: f32 = 0xaaaaaa.0p-24; const Lg2: f32 = 0xccce13.0p-25; const Lg3: f32 = 0x91e9ee.0p-25; @@ -95,8 +95,8 @@ pub fn log10_32(x_: f32) f32 { } pub fn log10_64(x_: f64) f64 { - const ivln10hi: f64 = 4.34294481878168880939e-01; - const ivln10lo: f64 = 2.50829467116452752298e-11; + const ivln10hi: f64 = 4.34294481878168880939e-01; + const ivln10lo: f64 = 2.50829467116452752298e-11; const log10_2hi: f64 = 3.01029995663611771306e-01; const log10_2lo: f64 = 3.69423907715893078616e-13; const Lg1: f64 = 6.666666666666735130e-01; @@ -126,11 +126,9 @@ pub fn log10_64(x_: f64) f64 { k -= 54; x *= 0x1.0p54; hx = u32(@bitCast(u64, x) >> 32); - } - else if (hx >= 0x7FF00000) { + } else if (hx >= 0x7FF00000) { return x; - } - else if (hx == 0x3FF00000 and ix << 32 == 0) { + } else if (hx == 0x3FF00000 and ix << 32 == 0) { return 0; } diff --git a/std/math/log2.zig b/std/math/log2.zig index d5bbe385c2ab16fa649ab0854d55e2a3338c927e..22cc8082b32102a201f93d3cc17160d2c8d4297e 100644 --- a/std/math/log2.zig +++ b/std/math/log2.zig @@ -27,7 +27,10 @@ pub fn log2(x: var) @typeOf(x) { TypeId.IntLiteral => comptime { var result = 0; var x_shifted = x; - while (b: {x_shifted >>= 1; break :b x_shifted != 0;}) : (result += 1) {} + while (b: { + x_shifted >>= 1; + break :b x_shifted != 0; + }) : (result += 1) {} return result; }, TypeId.Int => { @@ -38,7 +41,7 @@ pub fn log2(x: var) @typeOf(x) { } pub fn log2_32(x_: f32) f32 { - const ivln2hi: f32 = 1.4428710938e+00; + const ivln2hi: f32 = 1.4428710938e+00; const ivln2lo: f32 = -1.7605285393e-04; const Lg1: f32 = 0xaaaaaa.0p-24; const Lg2: f32 = 0xccce13.0p-25; diff --git a/std/math/round.zig b/std/math/round.zig index c16190da2182d7c06fd70bd8b6b67134ad092f43..c8d9eb4fd4656b3067aa205c928a3da4d88545f2 100644 --- a/std/math/round.zig +++ b/std/math/round.zig @@ -24,13 +24,13 @@ fn round32(x_: f32) f32 { const e = (u >> 23) & 0xFF; var y: f32 = undefined; - if (e >= 0x7F+23) { + if (e >= 0x7F + 23) { return x; } if (u >> 31 != 0) { x = -x; } - if (e < 0x7F-1) { + if (e < 0x7F - 1) { math.forceEval(x + math.f32_toint); return 0 * @bitCast(f32, u); } @@ -61,13 +61,13 @@ fn round64(x_: f64) f64 { const e = (u >> 52) & 0x7FF; var y: f64 = undefined; - if (e >= 0x3FF+52) { + if (e >= 0x3FF + 52) { return x; } if (u >> 63 != 0) { x = -x; } - if (e < 0x3ff-1) { + if (e < 0x3ff - 1) { math.forceEval(x + math.f64_toint); return 0 * @bitCast(f64, u); } diff --git a/std/math/sin.zig b/std/math/sin.zig index 5dd869545b820670f4fd2565a20d7d6508b94f85..21c324e444f259863994a4f69c8ebdce29e093e8 100644 --- a/std/math/sin.zig +++ b/std/math/sin.zig @@ -19,20 +19,20 @@ pub fn sin(x: var) @typeOf(x) { } // sin polynomial coefficients -const S0 = 1.58962301576546568060E-10; +const S0 = 1.58962301576546568060E-10; const S1 = -2.50507477628578072866E-8; -const S2 = 2.75573136213857245213E-6; +const S2 = 2.75573136213857245213E-6; const S3 = -1.98412698295895385996E-4; -const S4 = 8.33333333332211858878E-3; +const S4 = 8.33333333332211858878E-3; const S5 = -1.66666666666666307295E-1; // cos polynomial coeffiecients const C0 = -1.13585365213876817300E-11; -const C1 = 2.08757008419747316778E-9; +const C1 = 2.08757008419747316778E-9; const C2 = -2.75573141792967388112E-7; -const C3 = 2.48015872888517045348E-5; +const C3 = 2.48015872888517045348E-5; const C4 = -1.38888888888730564116E-3; -const C5 = 4.16666666666665929218E-2; +const C5 = 4.16666666666665929218E-2; // NOTE: This is taken from the go stdlib. The musl implementation is much more complex. // diff --git a/std/math/tan.zig b/std/math/tan.zig index 11428b6e8bc1156363bf717a6606f81a7db340c2..f578cf8156b2af6a1b63e7ad163b2b1d201cb699 100644 --- a/std/math/tan.zig +++ b/std/math/tan.zig @@ -19,12 +19,12 @@ pub fn tan(x: var) @typeOf(x) { } const Tp0 = -1.30936939181383777646E4; -const Tp1 = 1.15351664838587416140E6; +const Tp1 = 1.15351664838587416140E6; const Tp2 = -1.79565251976484877988E7; -const Tq1 = 1.36812963470692954678E4; +const Tq1 = 1.36812963470692954678E4; const Tq2 = -1.32089234440210967447E6; -const Tq3 = 2.50083801823357915839E7; +const Tq3 = 2.50083801823357915839E7; const Tq4 = -5.38695755929454629881E7; // NOTE: This is taken from the go stdlib. The musl implementation is much more complex. diff --git a/std/net.zig b/std/net.zig index 8e1b8d97b27b4e282da3a67adc035aa911d2d3ac..b1e291ab92d360ef6b155f89aa4ce36fa9d784c8 100644 --- a/std/net.zig +++ b/std/net.zig @@ -19,37 +19,29 @@ pub const Address = struct { os_addr: OsAddress, pub fn initIp4(ip4: u32, port: u16) Address { - return Address { - .os_addr = posix.sockaddr { - .in = posix.sockaddr_in { - .family = posix.AF_INET, - .port = std.mem.endianSwapIfLe(u16, port), - .addr = ip4, - .zero = []u8{0} ** 8, - }, - }, - }; + return Address{ .os_addr = posix.sockaddr{ .in = posix.sockaddr_in{ + .family = posix.AF_INET, + .port = std.mem.endianSwapIfLe(u16, port), + .addr = ip4, + .zero = []u8{0} ** 8, + } } }; } pub fn initIp6(ip6: &const Ip6Addr, port: u16) Address { - return Address { + return Address{ .family = posix.AF_INET6, - .os_addr = posix.sockaddr { - .in6 = posix.sockaddr_in6 { - .family = posix.AF_INET6, - .port = std.mem.endianSwapIfLe(u16, port), - .flowinfo = 0, - .addr = ip6.addr, - .scope_id = ip6.scope_id, - }, - }, + .os_addr = posix.sockaddr{ .in6 = posix.sockaddr_in6{ + .family = posix.AF_INET6, + .port = std.mem.endianSwapIfLe(u16, port), + .flowinfo = 0, + .addr = ip6.addr, + .scope_id = ip6.scope_id, + } }, }; } pub fn initPosix(addr: &const posix.sockaddr) Address { - return Address { - .os_addr = *addr, - }; + return Address{ .os_addr = addr.* }; } pub fn format(self: &const Address, out_stream: var) !void { @@ -98,7 +90,7 @@ pub fn parseIp4(buf: []const u8) !u32 { } } else { return error.InvalidCharacter; - } + } } if (index == 3 and saw_any_digits) { out_ptr[index] = x; diff --git a/std/os/child_process.zig b/std/os/child_process.zig index 8bb8b2d7e757414d850bddacc50678eb392519ce..6c0c21f64a7723761d88fa13c8c5019ba70a2ee1 100644 --- a/std/os/child_process.zig +++ b/std/os/child_process.zig @@ -49,7 +49,7 @@ pub const ChildProcess = struct { err_pipe: if (is_windows) void else [2]i32, llnode: if (is_windows) void else LinkedList(&ChildProcess).Node, - pub const SpawnError = error { + pub const SpawnError = error{ ProcessFdQuotaExceeded, Unexpected, NotDir, @@ -88,7 +88,7 @@ pub const ChildProcess = struct { const child = try allocator.create(ChildProcess); errdefer allocator.destroy(child); - *child = ChildProcess { + child.* = ChildProcess{ .allocator = allocator, .argv = argv, .pid = undefined, @@ -99,8 +99,10 @@ pub const ChildProcess = struct { .term = null, .env_map = null, .cwd = null, - .uid = if (is_windows) {} else null, - .gid = if (is_windows) {} else null, + .uid = if (is_windows) {} else + null, + .gid = if (is_windows) {} else + null, .stdin = null, .stdout = null, .stderr = null, @@ -193,9 +195,7 @@ pub const ChildProcess = struct { /// Spawns a child process, waits for it, collecting stdout and stderr, and then returns. /// If it succeeds, the caller owns result.stdout and result.stderr memory. - pub fn exec(allocator: &mem.Allocator, argv: []const []const u8, cwd: ?[]const u8, - env_map: ?&const BufMap, max_output_size: usize) !ExecResult - { + pub fn exec(allocator: &mem.Allocator, argv: []const []const u8, cwd: ?[]const u8, env_map: ?&const BufMap, max_output_size: usize) !ExecResult { const child = try ChildProcess.init(argv, allocator); defer child.deinit(); @@ -218,7 +218,7 @@ pub const ChildProcess = struct { try stdout_file_in_stream.stream.readAllBuffer(&stdout, max_output_size); try stderr_file_in_stream.stream.readAllBuffer(&stderr, max_output_size); - return ExecResult { + return ExecResult{ .term = try child.wait(), .stdout = stdout.toOwnedSlice(), .stderr = stderr.toOwnedSlice(), @@ -255,9 +255,9 @@ pub const ChildProcess = struct { self.term = (SpawnError!Term)(x: { var exit_code: windows.DWORD = undefined; if (windows.GetExitCodeProcess(self.handle, &exit_code) == 0) { - break :x Term { .Unknown = 0 }; + break :x Term{ .Unknown = 0 }; } else { - break :x Term { .Exited = @bitCast(i32, exit_code)}; + break :x Term{ .Exited = @bitCast(i32, exit_code) }; } }); @@ -288,9 +288,18 @@ pub const ChildProcess = struct { } fn cleanupStreams(self: &ChildProcess) void { - if (self.stdin) |*stdin| { stdin.close(); self.stdin = null; } - if (self.stdout) |*stdout| { stdout.close(); self.stdout = null; } - if (self.stderr) |*stderr| { stderr.close(); self.stderr = null; } + if (self.stdin) |*stdin| { + stdin.close(); + self.stdin = null; + } + if (self.stdout) |*stdout| { + stdout.close(); + self.stdout = null; + } + if (self.stderr) |*stderr| { + stderr.close(); + self.stderr = null; + } } fn cleanupAfterWait(self: &ChildProcess, status: i32) !Term { @@ -317,25 +326,30 @@ pub const ChildProcess = struct { fn statusToTerm(status: i32) Term { return if (posix.WIFEXITED(status)) - Term { .Exited = posix.WEXITSTATUS(status) } + Term{ .Exited = posix.WEXITSTATUS(status) } else if (posix.WIFSIGNALED(status)) - Term { .Signal = posix.WTERMSIG(status) } + Term{ .Signal = posix.WTERMSIG(status) } else if (posix.WIFSTOPPED(status)) - Term { .Stopped = posix.WSTOPSIG(status) } + Term{ .Stopped = posix.WSTOPSIG(status) } else - Term { .Unknown = status } - ; + Term{ .Unknown = status }; } fn spawnPosix(self: &ChildProcess) !void { const stdin_pipe = if (self.stdin_behavior == StdIo.Pipe) try makePipe() else undefined; - errdefer if (self.stdin_behavior == StdIo.Pipe) { destroyPipe(stdin_pipe); }; + errdefer if (self.stdin_behavior == StdIo.Pipe) { + destroyPipe(stdin_pipe); + }; const stdout_pipe = if (self.stdout_behavior == StdIo.Pipe) try makePipe() else undefined; - errdefer if (self.stdout_behavior == StdIo.Pipe) { destroyPipe(stdout_pipe); }; + errdefer if (self.stdout_behavior == StdIo.Pipe) { + destroyPipe(stdout_pipe); + }; const stderr_pipe = if (self.stderr_behavior == StdIo.Pipe) try makePipe() else undefined; - errdefer if (self.stderr_behavior == StdIo.Pipe) { destroyPipe(stderr_pipe); }; + errdefer if (self.stderr_behavior == StdIo.Pipe) { + destroyPipe(stderr_pipe); + }; const any_ignore = (self.stdin_behavior == StdIo.Ignore or self.stdout_behavior == StdIo.Ignore or self.stderr_behavior == StdIo.Ignore); const dev_null_fd = if (any_ignore) blk: { @@ -346,7 +360,9 @@ pub const ChildProcess = struct { } else blk: { break :blk undefined; }; - defer { if (any_ignore) os.close(dev_null_fd); } + defer { + if (any_ignore) os.close(dev_null_fd); + } var env_map_owned: BufMap = undefined; var we_own_env_map: bool = undefined; @@ -358,7 +374,9 @@ pub const ChildProcess = struct { env_map_owned = try os.getEnvMap(self.allocator); break :x &env_map_owned; }; - defer { if (we_own_env_map) env_map_owned.deinit(); } + defer { + if (we_own_env_map) env_map_owned.deinit(); + } // This pipe is used to communicate errors between the time of fork // and execve from the child process to the parent process. @@ -369,23 +387,21 @@ pub const ChildProcess = struct { const pid_err = posix.getErrno(pid_result); if (pid_err > 0) { return switch (pid_err) { - posix.EAGAIN, posix.ENOMEM, posix.ENOSYS => error.SystemResources, + posix.EAGAIN, + posix.ENOMEM, + posix.ENOSYS => error.SystemResources, else => os.unexpectedErrorPosix(pid_err), }; } if (pid_result == 0) { // we are the child - 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) catch - |err| forkChildErrReport(err_pipe[1], err); - setUpChildIo(self.stderr_behavior, stderr_pipe[1], posix.STDERR_FILENO, dev_null_fd) catch - |err| forkChildErrReport(err_pipe[1], err); + 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) catch |err| forkChildErrReport(err_pipe[1], err); + 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) catch - |err| forkChildErrReport(err_pipe[1], err); + os.changeCurDir(self.allocator, cwd) catch |err| forkChildErrReport(err_pipe[1], err); } if (self.gid) |gid| { @@ -396,8 +412,7 @@ pub const ChildProcess = struct { os.posix_setreuid(uid, uid) catch |err| forkChildErrReport(err_pipe[1], err); } - os.posixExecve(self.argv, env_map, self.allocator) catch - |err| forkChildErrReport(err_pipe[1], err); + os.posixExecve(self.argv, env_map, self.allocator) catch |err| forkChildErrReport(err_pipe[1], err); } // we are the parent @@ -423,37 +438,41 @@ pub const ChildProcess = struct { self.llnode = LinkedList(&ChildProcess).Node.init(self); self.term = null; - if (self.stdin_behavior == StdIo.Pipe) { os.close(stdin_pipe[0]); } - if (self.stdout_behavior == StdIo.Pipe) { os.close(stdout_pipe[1]); } - if (self.stderr_behavior == StdIo.Pipe) { os.close(stderr_pipe[1]); } + if (self.stdin_behavior == StdIo.Pipe) { + os.close(stdin_pipe[0]); + } + if (self.stdout_behavior == StdIo.Pipe) { + os.close(stdout_pipe[1]); + } + if (self.stderr_behavior == StdIo.Pipe) { + os.close(stderr_pipe[1]); + } } fn spawnWindows(self: &ChildProcess) !void { - const saAttr = windows.SECURITY_ATTRIBUTES { + const saAttr = windows.SECURITY_ATTRIBUTES{ .nLength = @sizeOf(windows.SECURITY_ATTRIBUTES), .bInheritHandle = windows.TRUE, .lpSecurityDescriptor = null, }; - const any_ignore = (self.stdin_behavior == StdIo.Ignore or - self.stdout_behavior == StdIo.Ignore or - self.stderr_behavior == StdIo.Ignore); + const any_ignore = (self.stdin_behavior == StdIo.Ignore or self.stdout_behavior == StdIo.Ignore or self.stderr_behavior == StdIo.Ignore); const nul_handle = if (any_ignore) blk: { const nul_file_path = "NUL"; var fixed_buffer_mem: [nul_file_path.len + 1]u8 = undefined; var fixed_allocator = std.heap.FixedBufferAllocator.init(fixed_buffer_mem[0..]); - break :blk try os.windowsOpen(&fixed_allocator.allocator, "NUL", windows.GENERIC_READ, windows.FILE_SHARE_READ, - windows.OPEN_EXISTING, windows.FILE_ATTRIBUTE_NORMAL); + break :blk try os.windowsOpen(&fixed_allocator.allocator, "NUL", windows.GENERIC_READ, windows.FILE_SHARE_READ, windows.OPEN_EXISTING, windows.FILE_ATTRIBUTE_NORMAL); } else blk: { break :blk undefined; }; - defer { if (any_ignore) os.close(nul_handle); } + defer { + if (any_ignore) os.close(nul_handle); + } if (any_ignore) { try windowsSetHandleInfo(nul_handle, windows.HANDLE_FLAG_INHERIT, 0); } - var g_hChildStd_IN_Rd: ?windows.HANDLE = null; var g_hChildStd_IN_Wr: ?windows.HANDLE = null; switch (self.stdin_behavior) { @@ -470,7 +489,9 @@ pub const ChildProcess = struct { g_hChildStd_IN_Rd = null; }, } - errdefer if (self.stdin_behavior == StdIo.Pipe) { windowsDestroyPipe(g_hChildStd_IN_Rd, g_hChildStd_IN_Wr); }; + errdefer if (self.stdin_behavior == StdIo.Pipe) { + windowsDestroyPipe(g_hChildStd_IN_Rd, g_hChildStd_IN_Wr); + }; var g_hChildStd_OUT_Rd: ?windows.HANDLE = null; var g_hChildStd_OUT_Wr: ?windows.HANDLE = null; @@ -488,7 +509,9 @@ pub const ChildProcess = struct { g_hChildStd_OUT_Wr = null; }, } - errdefer if (self.stdin_behavior == StdIo.Pipe) { windowsDestroyPipe(g_hChildStd_OUT_Rd, g_hChildStd_OUT_Wr); }; + errdefer if (self.stdin_behavior == StdIo.Pipe) { + windowsDestroyPipe(g_hChildStd_OUT_Rd, g_hChildStd_OUT_Wr); + }; var g_hChildStd_ERR_Rd: ?windows.HANDLE = null; var g_hChildStd_ERR_Wr: ?windows.HANDLE = null; @@ -506,12 +529,14 @@ pub const ChildProcess = struct { g_hChildStd_ERR_Wr = null; }, } - errdefer if (self.stdin_behavior == StdIo.Pipe) { windowsDestroyPipe(g_hChildStd_ERR_Rd, g_hChildStd_ERR_Wr); }; + errdefer if (self.stdin_behavior == StdIo.Pipe) { + windowsDestroyPipe(g_hChildStd_ERR_Rd, g_hChildStd_ERR_Wr); + }; const cmd_line = try windowsCreateCommandLine(self.allocator, self.argv); defer self.allocator.free(cmd_line); - var siStartInfo = windows.STARTUPINFOA { + var siStartInfo = windows.STARTUPINFOA{ .cb = @sizeOf(windows.STARTUPINFOA), .hStdError = g_hChildStd_ERR_Wr, .hStdOutput = g_hChildStd_OUT_Wr, @@ -534,19 +559,11 @@ pub const ChildProcess = struct { }; var piProcInfo: windows.PROCESS_INFORMATION = undefined; - const cwd_slice = if (self.cwd) |cwd| - try cstr.addNullByte(self.allocator, cwd) - else - null - ; + const cwd_slice = if (self.cwd) |cwd| try cstr.addNullByte(self.allocator, cwd) else null; defer if (cwd_slice) |cwd| self.allocator.free(cwd); const cwd_ptr = if (cwd_slice) |cwd| cwd.ptr else null; - const maybe_envp_buf = if (self.env_map) |env_map| - try os.createWindowsEnvBlock(self.allocator, env_map) - else - null - ; + const maybe_envp_buf = if (self.env_map) |env_map| try os.createWindowsEnvBlock(self.allocator, env_map) else null; defer if (maybe_envp_buf) |envp_buf| self.allocator.free(envp_buf); const envp_ptr = if (maybe_envp_buf) |envp_buf| envp_buf.ptr else null; @@ -563,11 +580,8 @@ pub const ChildProcess = struct { }; defer self.allocator.free(app_name); - windowsCreateProcess(app_name.ptr, cmd_line.ptr, envp_ptr, cwd_ptr, - &siStartInfo, &piProcInfo) catch |no_path_err| - { - if (no_path_err != error.FileNotFound) - return no_path_err; + windowsCreateProcess(app_name.ptr, cmd_line.ptr, envp_ptr, cwd_ptr, &siStartInfo, &piProcInfo) catch |no_path_err| { + if (no_path_err != error.FileNotFound) return no_path_err; const PATH = try os.getEnvVarOwned(self.allocator, "PATH"); defer self.allocator.free(PATH); @@ -577,9 +591,7 @@ pub const ChildProcess = struct { const joined_path = try os.path.join(self.allocator, search_path, app_name); defer self.allocator.free(joined_path); - if (windowsCreateProcess(joined_path.ptr, cmd_line.ptr, envp_ptr, cwd_ptr, - &siStartInfo, &piProcInfo)) |_| - { + if (windowsCreateProcess(joined_path.ptr, cmd_line.ptr, envp_ptr, cwd_ptr, &siStartInfo, &piProcInfo)) |_| { break; } else |err| if (err == error.FileNotFound) { continue; @@ -609,9 +621,15 @@ pub const ChildProcess = struct { self.thread_handle = piProcInfo.hThread; self.term = null; - if (self.stdin_behavior == StdIo.Pipe) { os.close(??g_hChildStd_IN_Rd); } - if (self.stderr_behavior == StdIo.Pipe) { os.close(??g_hChildStd_ERR_Wr); } - if (self.stdout_behavior == StdIo.Pipe) { os.close(??g_hChildStd_OUT_Wr); } + if (self.stdin_behavior == StdIo.Pipe) { + os.close(??g_hChildStd_IN_Rd); + } + if (self.stderr_behavior == StdIo.Pipe) { + os.close(??g_hChildStd_ERR_Wr); + } + if (self.stdout_behavior == StdIo.Pipe) { + os.close(??g_hChildStd_OUT_Wr); + } } fn setUpChildIo(stdio: StdIo, pipe_fd: i32, std_fileno: i32, dev_null_fd: i32) !void { @@ -622,18 +640,14 @@ pub const ChildProcess = struct { StdIo.Ignore => try os.posixDup2(dev_null_fd, std_fileno), } } - }; -fn windowsCreateProcess(app_name: &u8, cmd_line: &u8, envp_ptr: ?&u8, cwd_ptr: ?&u8, - lpStartupInfo: &windows.STARTUPINFOA, lpProcessInformation: &windows.PROCESS_INFORMATION) !void -{ - if (windows.CreateProcessA(app_name, cmd_line, null, null, windows.TRUE, 0, - @ptrCast(?&c_void, envp_ptr), cwd_ptr, lpStartupInfo, lpProcessInformation) == 0) - { +fn windowsCreateProcess(app_name: &u8, cmd_line: &u8, envp_ptr: ?&u8, cwd_ptr: ?&u8, lpStartupInfo: &windows.STARTUPINFOA, lpProcessInformation: &windows.PROCESS_INFORMATION) !void { + if (windows.CreateProcessA(app_name, cmd_line, null, null, windows.TRUE, 0, @ptrCast(?&c_void, envp_ptr), cwd_ptr, lpStartupInfo, lpProcessInformation) == 0) { const err = windows.GetLastError(); return switch (err) { - windows.ERROR.FILE_NOT_FOUND, windows.ERROR.PATH_NOT_FOUND => error.FileNotFound, + windows.ERROR.FILE_NOT_FOUND, + windows.ERROR.PATH_NOT_FOUND => error.FileNotFound, windows.ERROR.INVALID_PARAMETER => unreachable, windows.ERROR.INVALID_NAME => error.InvalidName, else => os.unexpectedErrorWindows(err), @@ -641,9 +655,6 @@ fn windowsCreateProcess(app_name: &u8, cmd_line: &u8, envp_ptr: ?&u8, cwd_ptr: ? } } - - - /// Caller must dealloc. /// Guarantees a null byte at result[result.len]. fn windowsCreateCommandLine(allocator: &mem.Allocator, argv: []const []const u8) ![]u8 { @@ -651,8 +662,7 @@ fn windowsCreateCommandLine(allocator: &mem.Allocator, argv: []const []const u8) defer buf.deinit(); for (argv) |arg, arg_i| { - if (arg_i != 0) - try buf.appendByte(' '); + if (arg_i != 0) try buf.appendByte(' '); if (mem.indexOfAny(u8, arg, " \t\n\"") == null) { try buf.append(arg); continue; @@ -686,7 +696,6 @@ fn windowsDestroyPipe(rd: ?windows.HANDLE, wr: ?windows.HANDLE) void { if (wr) |h| os.close(h); } - // TODO: workaround for bug where the `const` from `&const` is dropped when the type is // a namespace field lookup const SECURITY_ATTRIBUTES = windows.SECURITY_ATTRIBUTES; @@ -715,8 +724,8 @@ fn windowsMakePipeIn(rd: &?windows.HANDLE, wr: &?windows.HANDLE, sattr: &const S try windowsMakePipe(&rd_h, &wr_h, sattr); errdefer windowsDestroyPipe(rd_h, wr_h); try windowsSetHandleInfo(wr_h, windows.HANDLE_FLAG_INHERIT, 0); - *rd = rd_h; - *wr = wr_h; + rd.* = rd_h; + wr.* = wr_h; } fn windowsMakePipeOut(rd: &?windows.HANDLE, wr: &?windows.HANDLE, sattr: &const SECURITY_ATTRIBUTES) !void { @@ -725,8 +734,8 @@ fn windowsMakePipeOut(rd: &?windows.HANDLE, wr: &?windows.HANDLE, sattr: &const try windowsMakePipe(&rd_h, &wr_h, sattr); errdefer windowsDestroyPipe(rd_h, wr_h); try windowsSetHandleInfo(rd_h, windows.HANDLE_FLAG_INHERIT, 0); - *rd = rd_h; - *wr = wr_h; + rd.* = rd_h; + wr.* = wr_h; } fn makePipe() ![2]i32 { @@ -734,7 +743,8 @@ fn makePipe() ![2]i32 { const err = posix.getErrno(posix.pipe(&fds)); if (err > 0) { return switch (err) { - posix.EMFILE, posix.ENFILE => error.SystemResources, + posix.EMFILE, + posix.ENFILE => error.SystemResources, else => os.unexpectedErrorPosix(err), }; } @@ -742,8 +752,8 @@ fn makePipe() ![2]i32 { } fn destroyPipe(pipe: &const [2]i32) void { - os.close((*pipe)[0]); - os.close((*pipe)[1]); + os.close((pipe.*)[0]); + os.close((pipe.*)[1]); } // Child of fork calls this to report an error to the fork parent. diff --git a/std/segmented_list.zig b/std/segmented_list.zig index 6c7c8799194e586020120d2ff0b4c843db9694fd..e9abc7adf913811ec22d587dbb333507cea7c69b 100644 --- a/std/segmented_list.zig +++ b/std/segmented_list.zig @@ -93,7 +93,7 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type /// Deinitialize with `deinit` pub fn init(allocator: &Allocator) Self { - return Self { + return Self{ .allocator = allocator, .len = 0, .prealloc_segment = undefined, @@ -104,7 +104,7 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type pub fn deinit(self: &Self) void { self.freeShelves(ShelfIndex(self.dynamic_segments.len), 0); self.allocator.free(self.dynamic_segments); - *self = undefined; + self.* = undefined; } pub fn at(self: &Self, i: usize) &T { @@ -118,7 +118,7 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type pub fn push(self: &Self, item: &const T) !void { const new_item_ptr = try self.addOne(); - *new_item_ptr = *item; + new_item_ptr.* = item.*; } pub fn pushMany(self: &Self, items: []const T) !void { @@ -128,11 +128,10 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type } pub fn pop(self: &Self) ?T { - if (self.len == 0) - return null; + if (self.len == 0) return null; const index = self.len - 1; - const result = *self.uncheckedAt(index); + const result = self.uncheckedAt(index).*; self.len = index; return result; } @@ -245,8 +244,7 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type shelf_size: usize, pub fn next(it: &Iterator) ?&T { - if (it.index >= it.list.len) - return null; + if (it.index >= it.list.len) return null; if (it.index < prealloc_item_count) { const ptr = &it.list.prealloc_segment[it.index]; it.index += 1; @@ -270,12 +268,10 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type } pub fn prev(it: &Iterator) ?&T { - if (it.index == 0) - return null; + if (it.index == 0) return null; it.index -= 1; - if (it.index < prealloc_item_count) - return &it.list.prealloc_segment[it.index]; + if (it.index < prealloc_item_count) return &it.list.prealloc_segment[it.index]; if (it.box_index == 0) { it.shelf_index -= 1; @@ -290,7 +286,7 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type }; pub fn iterator(self: &Self, start_index: usize) Iterator { - var it = Iterator { + var it = Iterator{ .list = self, .index = start_index, .shelf_index = undefined, @@ -324,25 +320,31 @@ fn testSegmentedList(comptime prealloc: usize, allocator: &Allocator) !void { var list = SegmentedList(i32, prealloc).init(allocator); defer list.deinit(); - {var i: usize = 0; while (i < 100) : (i += 1) { - try list.push(i32(i + 1)); - assert(list.len == i + 1); - }} + { + var i: usize = 0; + while (i < 100) : (i += 1) { + try list.push(i32(i + 1)); + assert(list.len == i + 1); + } + } - {var i: usize = 0; while (i < 100) : (i += 1) { - assert(*list.at(i) == i32(i + 1)); - }} + { + var i: usize = 0; + while (i < 100) : (i += 1) { + assert(list.at(i).* == i32(i + 1)); + } + } { var it = list.iterator(0); var x: i32 = 0; while (it.next()) |item| { x += 1; - assert(*item == x); + assert(item.* == x); } assert(x == 100); while (it.prev()) |item| : (x -= 1) { - assert(*item == x); + assert(item.* == x); } assert(x == 0); } @@ -350,14 +352,18 @@ fn testSegmentedList(comptime prealloc: usize, allocator: &Allocator) !void { assert(??list.pop() == 100); assert(list.len == 99); - try list.pushMany([]i32 { 1, 2, 3 }); + try list.pushMany([]i32{ + 1, + 2, + 3, + }); assert(list.len == 102); assert(??list.pop() == 3); assert(??list.pop() == 2); assert(??list.pop() == 1); assert(list.len == 99); - try list.pushMany([]const i32 {}); + try list.pushMany([]const i32{}); assert(list.len == 99); var i: i32 = 99; diff --git a/std/sort.zig b/std/sort.zig index 0f83df7bb46dd103e4b9b7cc3743e1792116c7d2..4cc7ad503a400cb1150af63dbd315d0213cf340a 100644 --- a/std/sort.zig +++ b/std/sort.zig @@ -5,15 +5,18 @@ const math = std.math; const builtin = @import("builtin"); /// Stable in-place sort. O(n) best case, O(pow(n, 2)) worst case. O(1) memory (no allocator required). -pub fn insertionSort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &const T)bool) void { - {var i: usize = 1; while (i < items.len) : (i += 1) { - const x = items[i]; - var j: usize = i; - while (j > 0 and lessThan(x, items[j - 1])) : (j -= 1) { - items[j] = items[j - 1]; +pub fn insertionSort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &const T) bool) void { + { + var i: usize = 1; + while (i < items.len) : (i += 1) { + const x = items[i]; + var j: usize = i; + while (j > 0 and lessThan(x, items[j - 1])) : (j -= 1) { + items[j] = items[j - 1]; + } + items[j] = x; } - items[j] = x; - }} + } } const Range = struct { @@ -21,7 +24,10 @@ const Range = struct { end: usize, fn init(start: usize, end: usize) Range { - return Range { .start = start, .end = end }; + return Range{ + .start = start, + .end = end, + }; } fn length(self: &const Range) usize { @@ -29,7 +35,6 @@ const Range = struct { } }; - const Iterator = struct { size: usize, power_of_two: usize, @@ -42,7 +47,7 @@ const Iterator = struct { fn init(size2: usize, min_level: usize) Iterator { const power_of_two = math.floorPowerOfTwo(usize, size2); const denominator = power_of_two / min_level; - return Iterator { + return Iterator{ .numerator = 0, .decimal = 0, .size = size2, @@ -68,7 +73,10 @@ const Iterator = struct { self.decimal += 1; } - return Range {.start = start, .end = self.decimal}; + return Range{ + .start = start, + .end = self.decimal, + }; } fn finished(self: &Iterator) bool { @@ -100,7 +108,7 @@ const Pull = struct { /// Stable in-place sort. O(n) best case, O(n*log(n)) worst case and average case. O(1) memory (no allocator required). /// Currently implemented as block sort. -pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &const T)bool) void { +pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &const T) bool) void { // Implementation ported from https://github.com/BonzaiThePenguin/WikiSort/blob/master/WikiSort.c var cache: [512]T = undefined; @@ -123,7 +131,16 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons // http://pages.ripco.net/~jgamble/nw.html var iterator = Iterator.init(items.len, 4); while (!iterator.finished()) { - var order = []u8{0, 1, 2, 3, 4, 5, 6, 7}; + var order = []u8{ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + }; const range = iterator.nextRange(); const sliced_items = items[range.start..]; @@ -149,56 +166,56 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons swap(T, sliced_items, lessThan, &order, 3, 5); swap(T, sliced_items, lessThan, &order, 3, 4); }, - 7 => { - swap(T, sliced_items, lessThan, &order, 1, 2); - swap(T, sliced_items, lessThan, &order, 3, 4); - swap(T, sliced_items, lessThan, &order, 5, 6); - swap(T, sliced_items, lessThan, &order, 0, 2); - swap(T, sliced_items, lessThan, &order, 3, 5); - swap(T, sliced_items, lessThan, &order, 4, 6); - swap(T, sliced_items, lessThan, &order, 0, 1); - swap(T, sliced_items, lessThan, &order, 4, 5); - swap(T, sliced_items, lessThan, &order, 2, 6); - swap(T, sliced_items, lessThan, &order, 0, 4); - swap(T, sliced_items, lessThan, &order, 1, 5); - swap(T, sliced_items, lessThan, &order, 0, 3); - swap(T, sliced_items, lessThan, &order, 2, 5); - swap(T, sliced_items, lessThan, &order, 1, 3); - swap(T, sliced_items, lessThan, &order, 2, 4); - swap(T, sliced_items, lessThan, &order, 2, 3); - }, - 6 => { - swap(T, sliced_items, lessThan, &order, 1, 2); - swap(T, sliced_items, lessThan, &order, 4, 5); - swap(T, sliced_items, lessThan, &order, 0, 2); - swap(T, sliced_items, lessThan, &order, 3, 5); - swap(T, sliced_items, lessThan, &order, 0, 1); - swap(T, sliced_items, lessThan, &order, 3, 4); - swap(T, sliced_items, lessThan, &order, 2, 5); - swap(T, sliced_items, lessThan, &order, 0, 3); - swap(T, sliced_items, lessThan, &order, 1, 4); - swap(T, sliced_items, lessThan, &order, 2, 4); - swap(T, sliced_items, lessThan, &order, 1, 3); - swap(T, sliced_items, lessThan, &order, 2, 3); - }, - 5 => { - swap(T, sliced_items, lessThan, &order, 0, 1); - swap(T, sliced_items, lessThan, &order, 3, 4); - swap(T, sliced_items, lessThan, &order, 2, 4); - swap(T, sliced_items, lessThan, &order, 2, 3); - swap(T, sliced_items, lessThan, &order, 1, 4); - swap(T, sliced_items, lessThan, &order, 0, 3); - swap(T, sliced_items, lessThan, &order, 0, 2); - swap(T, sliced_items, lessThan, &order, 1, 3); - swap(T, sliced_items, lessThan, &order, 1, 2); - }, - 4 => { - swap(T, sliced_items, lessThan, &order, 0, 1); - swap(T, sliced_items, lessThan, &order, 2, 3); - swap(T, sliced_items, lessThan, &order, 0, 2); - swap(T, sliced_items, lessThan, &order, 1, 3); - swap(T, sliced_items, lessThan, &order, 1, 2); - }, + 7 => { + swap(T, sliced_items, lessThan, &order, 1, 2); + swap(T, sliced_items, lessThan, &order, 3, 4); + swap(T, sliced_items, lessThan, &order, 5, 6); + swap(T, sliced_items, lessThan, &order, 0, 2); + swap(T, sliced_items, lessThan, &order, 3, 5); + swap(T, sliced_items, lessThan, &order, 4, 6); + swap(T, sliced_items, lessThan, &order, 0, 1); + swap(T, sliced_items, lessThan, &order, 4, 5); + swap(T, sliced_items, lessThan, &order, 2, 6); + swap(T, sliced_items, lessThan, &order, 0, 4); + swap(T, sliced_items, lessThan, &order, 1, 5); + swap(T, sliced_items, lessThan, &order, 0, 3); + swap(T, sliced_items, lessThan, &order, 2, 5); + swap(T, sliced_items, lessThan, &order, 1, 3); + swap(T, sliced_items, lessThan, &order, 2, 4); + swap(T, sliced_items, lessThan, &order, 2, 3); + }, + 6 => { + swap(T, sliced_items, lessThan, &order, 1, 2); + swap(T, sliced_items, lessThan, &order, 4, 5); + swap(T, sliced_items, lessThan, &order, 0, 2); + swap(T, sliced_items, lessThan, &order, 3, 5); + swap(T, sliced_items, lessThan, &order, 0, 1); + swap(T, sliced_items, lessThan, &order, 3, 4); + swap(T, sliced_items, lessThan, &order, 2, 5); + swap(T, sliced_items, lessThan, &order, 0, 3); + swap(T, sliced_items, lessThan, &order, 1, 4); + swap(T, sliced_items, lessThan, &order, 2, 4); + swap(T, sliced_items, lessThan, &order, 1, 3); + swap(T, sliced_items, lessThan, &order, 2, 3); + }, + 5 => { + swap(T, sliced_items, lessThan, &order, 0, 1); + swap(T, sliced_items, lessThan, &order, 3, 4); + swap(T, sliced_items, lessThan, &order, 2, 4); + swap(T, sliced_items, lessThan, &order, 2, 3); + swap(T, sliced_items, lessThan, &order, 1, 4); + swap(T, sliced_items, lessThan, &order, 0, 3); + swap(T, sliced_items, lessThan, &order, 0, 2); + swap(T, sliced_items, lessThan, &order, 1, 3); + swap(T, sliced_items, lessThan, &order, 1, 2); + }, + 4 => { + swap(T, sliced_items, lessThan, &order, 0, 1); + swap(T, sliced_items, lessThan, &order, 2, 3); + swap(T, sliced_items, lessThan, &order, 0, 2); + swap(T, sliced_items, lessThan, &order, 1, 3); + swap(T, sliced_items, lessThan, &order, 1, 2); + }, else => {}, } } @@ -273,7 +290,6 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons // we merged two levels at the same time, so we're done with this level already // (iterator.nextLevel() is called again at the bottom of this outer merge loop) _ = iterator.nextLevel(); - } else { iterator.begin(); while (!iterator.finished()) { @@ -303,7 +319,7 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons // 8. redistribute the two internal buffers back into the items var block_size: usize = math.sqrt(iterator.length()); - var buffer_size = iterator.length()/block_size + 1; + var buffer_size = iterator.length() / block_size + 1; // as an optimization, we really only need to pull out the internal buffers once for each level of merges // after that we can reuse the same buffers over and over, then redistribute it when we're finished with this level @@ -316,8 +332,18 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons var start: usize = 0; var pull_index: usize = 0; var pull = []Pull{ - Pull {.from = 0, .to = 0, .count = 0, .range = Range.init(0, 0),}, - Pull {.from = 0, .to = 0, .count = 0, .range = Range.init(0, 0),}, + Pull{ + .from = 0, + .to = 0, + .count = 0, + .range = Range.init(0, 0), + }, + Pull{ + .from = 0, + .to = 0, + .count = 0, + .range = Range.init(0, 0), + }, }; var buffer1 = Range.init(0, 0); @@ -355,7 +381,10 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons // these values will be pulled out to the start of A last = A.start; count = 1; - while (count < find) : ({last = index; count += 1;}) { + while (count < find) : ({ + last = index; + count += 1; + }) { index = findLastForward(T, items, items[last], Range.init(last + 1, A.end), lessThan, find - count); if (index == A.end) break; } @@ -363,7 +392,7 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons if (count >= buffer_size) { // keep track of the range within the items where we'll need to "pull out" these values to create the internal buffer - pull[pull_index] = Pull { + pull[pull_index] = Pull{ .range = Range.init(A.start, B.end), .count = count, .from = index, @@ -398,7 +427,7 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons } else if (pull_index == 0 and count > buffer1.length()) { // keep track of the largest buffer we were able to find buffer1 = Range.init(A.start, A.start + count); - pull[pull_index] = Pull { + pull[pull_index] = Pull{ .range = Range.init(A.start, B.end), .count = count, .from = index, @@ -410,7 +439,10 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons // these values will be pulled out to the end of B last = B.end - 1; count = 1; - while (count < find) : ({last = index - 1; count += 1;}) { + while (count < find) : ({ + last = index - 1; + count += 1; + }) { index = findFirstBackward(T, items, items[last], Range.init(B.start, last), lessThan, find - count); if (index == B.start) break; } @@ -418,7 +450,7 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons if (count >= buffer_size) { // keep track of the range within the items where we'll need to "pull out" these values to create the internal buffe - pull[pull_index] = Pull { + pull[pull_index] = Pull{ .range = Range.init(A.start, B.end), .count = count, .from = index, @@ -457,7 +489,7 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons } else if (pull_index == 0 and count > buffer1.length()) { // keep track of the largest buffer we were able to find buffer1 = Range.init(B.end - count, B.end); - pull[pull_index] = Pull { + pull[pull_index] = Pull{ .range = Range.init(A.start, B.end), .count = count, .from = index, @@ -496,7 +528,7 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons // adjust block_size and buffer_size based on the values we were able to pull out buffer_size = buffer1.length(); - block_size = iterator.length()/buffer_size + 1; + block_size = iterator.length() / buffer_size + 1; // the first buffer NEEDS to be large enough to tag each of the evenly sized A blocks, // so this was originally here to test the math for adjusting block_size above @@ -547,7 +579,10 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons // swap the first value of each A block with the value in buffer1 var indexA = buffer1.start; index = firstA.end; - while (index < blockA.end) : ({indexA += 1; index += block_size;}) { + while (index < blockA.end) : ({ + indexA += 1; + index += block_size; + }) { mem.swap(T, &items[indexA], &items[index]); } @@ -626,9 +661,7 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons // if there are no more A blocks remaining, this step is finished! blockA.start += block_size; - if (blockA.length() == 0) - break; - + if (blockA.length() == 0) break; } else if (blockB.length() < block_size) { // move the last B block, which is unevenly sized, to before the remaining A blocks, by using a rotation // the cache is disabled here since it might contain the contents of the previous A block @@ -709,7 +742,7 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons } // merge operation without a buffer -fn mergeInPlace(comptime T: type, items: []T, A_arg: &const Range, B_arg: &const Range, lessThan: fn(&const T,&const T)bool) void { +fn mergeInPlace(comptime T: type, items: []T, A_arg: &const Range, B_arg: &const Range, lessThan: fn(&const T, &const T) bool) void { if (A_arg.length() == 0 or B_arg.length() == 0) return; // this just repeatedly binary searches into B and rotates A into position. @@ -730,8 +763,8 @@ fn mergeInPlace(comptime T: type, items: []T, A_arg: &const Range, B_arg: &const // again, this is NOT a general-purpose solution – it only works well in this case! // kind of like how the O(n^2) insertion sort is used in some places - var A = *A_arg; - var B = *B_arg; + var A = A_arg.*; + var B = B_arg.*; while (true) { // find the first place in B where the first item in A needs to be inserted @@ -751,7 +784,7 @@ fn mergeInPlace(comptime T: type, items: []T, A_arg: &const Range, B_arg: &const } // merge operation using an internal buffer -fn mergeInternal(comptime T: type, items: []T, A: &const Range, B: &const Range, lessThan: fn(&const T,&const T)bool, buffer: &const Range) void { +fn mergeInternal(comptime T: type, items: []T, A: &const Range, B: &const Range, lessThan: fn(&const T, &const T) bool, buffer: &const Range) void { // whenever we find a value to add to the final array, swap it with the value that's already in that spot // when this algorithm is finished, 'buffer' will contain its original contents, but in a different order var A_count: usize = 0; @@ -787,9 +820,9 @@ fn blockSwap(comptime T: type, items: []T, start1: usize, start2: usize, block_s // combine a linear search with a binary search to reduce the number of comparisons in situations // where have some idea as to how many unique values there are and where the next value might be -fn findFirstForward(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T,&const T)bool, unique: usize) usize { +fn findFirstForward(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T, &const T) bool, unique: usize) usize { if (range.length() == 0) return range.start; - const skip = math.max(range.length()/unique, usize(1)); + const skip = math.max(range.length() / unique, usize(1)); var index = range.start + skip; while (lessThan(items[index - 1], value)) : (index += skip) { @@ -801,9 +834,9 @@ fn findFirstForward(comptime T: type, items: []T, value: &const T, range: &const return binaryFirst(T, items, value, Range.init(index - skip, index), lessThan); } -fn findFirstBackward(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T,&const T)bool, unique: usize) usize { +fn findFirstBackward(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T, &const T) bool, unique: usize) usize { if (range.length() == 0) return range.start; - const skip = math.max(range.length()/unique, usize(1)); + const skip = math.max(range.length() / unique, usize(1)); var index = range.end - skip; while (index > range.start and !lessThan(items[index - 1], value)) : (index -= skip) { @@ -815,9 +848,9 @@ fn findFirstBackward(comptime T: type, items: []T, value: &const T, range: &cons return binaryFirst(T, items, value, Range.init(index, index + skip), lessThan); } -fn findLastForward(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T,&const T)bool, unique: usize) usize { +fn findLastForward(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T, &const T) bool, unique: usize) usize { if (range.length() == 0) return range.start; - const skip = math.max(range.length()/unique, usize(1)); + const skip = math.max(range.length() / unique, usize(1)); var index = range.start + skip; while (!lessThan(value, items[index - 1])) : (index += skip) { @@ -829,9 +862,9 @@ fn findLastForward(comptime T: type, items: []T, value: &const T, range: &const return binaryLast(T, items, value, Range.init(index - skip, index), lessThan); } -fn findLastBackward(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T,&const T)bool, unique: usize) usize { +fn findLastBackward(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T, &const T) bool, unique: usize) usize { if (range.length() == 0) return range.start; - const skip = math.max(range.length()/unique, usize(1)); + const skip = math.max(range.length() / unique, usize(1)); var index = range.end - skip; while (index > range.start and lessThan(value, items[index - 1])) : (index -= skip) { @@ -843,12 +876,12 @@ fn findLastBackward(comptime T: type, items: []T, value: &const T, range: &const return binaryLast(T, items, value, Range.init(index, index + skip), lessThan); } -fn binaryFirst(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T,&const T)bool) usize { +fn binaryFirst(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T, &const T) bool) usize { var start = range.start; var end = range.end - 1; if (range.start >= range.end) return range.end; while (start < end) { - const mid = start + (end - start)/2; + const mid = start + (end - start) / 2; if (lessThan(items[mid], value)) { start = mid + 1; } else { @@ -861,12 +894,12 @@ fn binaryFirst(comptime T: type, items: []T, value: &const T, range: &const Rang return start; } -fn binaryLast(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T,&const T)bool) usize { +fn binaryLast(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T, &const T) bool) usize { var start = range.start; var end = range.end - 1; if (range.start >= range.end) return range.end; while (start < end) { - const mid = start + (end - start)/2; + const mid = start + (end - start) / 2; if (!lessThan(value, items[mid])) { start = mid + 1; } else { @@ -879,7 +912,7 @@ fn binaryLast(comptime T: type, items: []T, value: &const T, range: &const Range return start; } -fn mergeInto(comptime T: type, from: []T, A: &const Range, B: &const Range, lessThan: fn(&const T,&const T)bool, into: []T) void { +fn mergeInto(comptime T: type, from: []T, A: &const Range, B: &const Range, lessThan: fn(&const T, &const T) bool, into: []T) void { var A_index: usize = A.start; var B_index: usize = B.start; const A_last = A.end; @@ -909,7 +942,7 @@ fn mergeInto(comptime T: type, from: []T, A: &const Range, B: &const Range, less } } -fn mergeExternal(comptime T: type, items: []T, A: &const Range, B: &const Range, lessThan: fn(&const T,&const T)bool, cache: []T) void { +fn mergeExternal(comptime T: type, items: []T, A: &const Range, B: &const Range, lessThan: fn(&const T, &const T) bool, cache: []T) void { // A fits into the cache, so use that instead of the internal buffer var A_index: usize = 0; var B_index: usize = B.start; @@ -937,29 +970,27 @@ fn mergeExternal(comptime T: type, items: []T, A: &const Range, B: &const Range, mem.copy(T, items[insert_index..], cache[A_index..A_last]); } -fn swap(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &const T)bool, order: &[8]u8, x: usize, y: usize) void { - if (lessThan(items[y], items[x]) or - ((*order)[x] > (*order)[y] and !lessThan(items[x], items[y]))) - { +fn swap(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &const T) bool, order: &[8]u8, x: usize, y: usize) void { + if (lessThan(items[y], items[x]) or ((order.*)[x] > (order.*)[y] and !lessThan(items[x], items[y]))) { mem.swap(T, &items[x], &items[y]); - mem.swap(u8, &(*order)[x], &(*order)[y]); + mem.swap(u8, &(order.*)[x], &(order.*)[y]); } } fn i32asc(lhs: &const i32, rhs: &const i32) bool { - return *lhs < *rhs; + return lhs.* < rhs.*; } fn i32desc(lhs: &const i32, rhs: &const i32) bool { - return *rhs < *lhs; + return rhs.* < lhs.*; } fn u8asc(lhs: &const u8, rhs: &const u8) bool { - return *lhs < *rhs; + return lhs.* < rhs.*; } fn u8desc(lhs: &const u8, rhs: &const u8) bool { - return *rhs < *lhs; + return rhs.* < lhs.*; } test "stable sort" { @@ -967,44 +998,125 @@ test "stable sort" { comptime testStableSort(); } fn testStableSort() void { - var expected = []IdAndValue { - IdAndValue{.id = 0, .value = 0}, - IdAndValue{.id = 1, .value = 0}, - IdAndValue{.id = 2, .value = 0}, - IdAndValue{.id = 0, .value = 1}, - IdAndValue{.id = 1, .value = 1}, - IdAndValue{.id = 2, .value = 1}, - IdAndValue{.id = 0, .value = 2}, - IdAndValue{.id = 1, .value = 2}, - IdAndValue{.id = 2, .value = 2}, + var expected = []IdAndValue{ + IdAndValue{ + .id = 0, + .value = 0, + }, + IdAndValue{ + .id = 1, + .value = 0, + }, + IdAndValue{ + .id = 2, + .value = 0, + }, + IdAndValue{ + .id = 0, + .value = 1, + }, + IdAndValue{ + .id = 1, + .value = 1, + }, + IdAndValue{ + .id = 2, + .value = 1, + }, + IdAndValue{ + .id = 0, + .value = 2, + }, + IdAndValue{ + .id = 1, + .value = 2, + }, + IdAndValue{ + .id = 2, + .value = 2, + }, }; - var cases = [][9]IdAndValue { - []IdAndValue { - IdAndValue{.id = 0, .value = 0}, - IdAndValue{.id = 0, .value = 1}, - IdAndValue{.id = 0, .value = 2}, - IdAndValue{.id = 1, .value = 0}, - IdAndValue{.id = 1, .value = 1}, - IdAndValue{.id = 1, .value = 2}, - IdAndValue{.id = 2, .value = 0}, - IdAndValue{.id = 2, .value = 1}, - IdAndValue{.id = 2, .value = 2}, + var cases = [][9]IdAndValue{ + []IdAndValue{ + IdAndValue{ + .id = 0, + .value = 0, + }, + IdAndValue{ + .id = 0, + .value = 1, + }, + IdAndValue{ + .id = 0, + .value = 2, + }, + IdAndValue{ + .id = 1, + .value = 0, + }, + IdAndValue{ + .id = 1, + .value = 1, + }, + IdAndValue{ + .id = 1, + .value = 2, + }, + IdAndValue{ + .id = 2, + .value = 0, + }, + IdAndValue{ + .id = 2, + .value = 1, + }, + IdAndValue{ + .id = 2, + .value = 2, + }, }, - []IdAndValue { - IdAndValue{.id = 0, .value = 2}, - IdAndValue{.id = 0, .value = 1}, - IdAndValue{.id = 0, .value = 0}, - IdAndValue{.id = 1, .value = 2}, - IdAndValue{.id = 1, .value = 1}, - IdAndValue{.id = 1, .value = 0}, - IdAndValue{.id = 2, .value = 2}, - IdAndValue{.id = 2, .value = 1}, - IdAndValue{.id = 2, .value = 0}, + []IdAndValue{ + IdAndValue{ + .id = 0, + .value = 2, + }, + IdAndValue{ + .id = 0, + .value = 1, + }, + IdAndValue{ + .id = 0, + .value = 0, + }, + IdAndValue{ + .id = 1, + .value = 2, + }, + IdAndValue{ + .id = 1, + .value = 1, + }, + IdAndValue{ + .id = 1, + .value = 0, + }, + IdAndValue{ + .id = 2, + .value = 2, + }, + IdAndValue{ + .id = 2, + .value = 1, + }, + IdAndValue{ + .id = 2, + .value = 0, + }, }, }; for (cases) |*case| { - insertionSort(IdAndValue, (*case)[0..], cmpByValue); - for (*case) |item, i| { + insertionSort(IdAndValue, (case.*)[0..], cmpByValue); + for (case.*) |item, i| { assert(item.id == expected[i].id); assert(item.value == expected[i].value); } @@ -1019,13 +1131,31 @@ fn cmpByValue(a: &const IdAndValue, b: &const IdAndValue) bool { } test "std.sort" { - const u8cases = [][]const []const u8 { - [][]const u8{"", ""}, - [][]const u8{"a", "a"}, - [][]const u8{"az", "az"}, - [][]const u8{"za", "az"}, - [][]const u8{"asdf", "adfs"}, - [][]const u8{"one", "eno"}, + const u8cases = [][]const []const u8{ + [][]const u8{ + "", + "", + }, + [][]const u8{ + "a", + "a", + }, + [][]const u8{ + "az", + "az", + }, + [][]const u8{ + "za", + "az", + }, + [][]const u8{ + "asdf", + "adfs", + }, + [][]const u8{ + "one", + "eno", + }, }; for (u8cases) |case| { @@ -1036,13 +1166,59 @@ test "std.sort" { assert(mem.eql(u8, slice, case[1])); } - const i32cases = [][]const []const i32 { - [][]const i32{[]i32{}, []i32{}}, - [][]const i32{[]i32{1}, []i32{1}}, - [][]const i32{[]i32{0, 1}, []i32{0, 1}}, - [][]const i32{[]i32{1, 0}, []i32{0, 1}}, - [][]const i32{[]i32{1, -1, 0}, []i32{-1, 0, 1}}, - [][]const i32{[]i32{2, 1, 3}, []i32{1, 2, 3}}, + const i32cases = [][]const []const i32{ + [][]const i32{ + []i32{}, + []i32{}, + }, + [][]const i32{ + []i32{1}, + []i32{1}, + }, + [][]const i32{ + []i32{ + 0, + 1, + }, + []i32{ + 0, + 1, + }, + }, + [][]const i32{ + []i32{ + 1, + 0, + }, + []i32{ + 0, + 1, + }, + }, + [][]const i32{ + []i32{ + 1, + -1, + 0, + }, + []i32{ + -1, + 0, + 1, + }, + }, + [][]const i32{ + []i32{ + 2, + 1, + 3, + }, + []i32{ + 1, + 2, + 3, + }, + }, }; for (i32cases) |case| { @@ -1055,13 +1231,59 @@ test "std.sort" { } test "std.sort descending" { - const rev_cases = [][]const []const i32 { - [][]const i32{[]i32{}, []i32{}}, - [][]const i32{[]i32{1}, []i32{1}}, - [][]const i32{[]i32{0, 1}, []i32{1, 0}}, - [][]const i32{[]i32{1, 0}, []i32{1, 0}}, - [][]const i32{[]i32{1, -1, 0}, []i32{1, 0, -1}}, - [][]const i32{[]i32{2, 1, 3}, []i32{3, 2, 1}}, + const rev_cases = [][]const []const i32{ + [][]const i32{ + []i32{}, + []i32{}, + }, + [][]const i32{ + []i32{1}, + []i32{1}, + }, + [][]const i32{ + []i32{ + 0, + 1, + }, + []i32{ + 1, + 0, + }, + }, + [][]const i32{ + []i32{ + 1, + 0, + }, + []i32{ + 1, + 0, + }, + }, + [][]const i32{ + []i32{ + 1, + -1, + 0, + }, + []i32{ + 1, + 0, + -1, + }, + }, + [][]const i32{ + []i32{ + 2, + 1, + 3, + }, + []i32{ + 3, + 2, + 1, + }, + }, }; for (rev_cases) |case| { @@ -1074,10 +1296,22 @@ test "std.sort descending" { } test "another sort case" { - var arr = []i32{ 5, 3, 1, 2, 4 }; + var arr = []i32{ + 5, + 3, + 1, + 2, + 4, + }; sort(i32, arr[0..], i32asc); - assert(mem.eql(i32, arr, []i32{ 1, 2, 3, 4, 5 })); + assert(mem.eql(i32, arr, []i32{ + 1, + 2, + 3, + 4, + 5, + })); } test "sort fuzz testing" { @@ -1112,7 +1346,7 @@ fn fuzzTest(rng: &std.rand.Random) void { } } -pub fn min(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &const T)bool) T { +pub fn min(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &const T) bool) T { var i: usize = 0; var smallest = items[0]; for (items[1..]) |item| { @@ -1123,7 +1357,7 @@ pub fn min(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &const return smallest; } -pub fn max(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &const T)bool) T { +pub fn max(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &const T) bool) T { var i: usize = 0; var biggest = items[0]; for (items[1..]) |item| { -- 2.54.0 From 6e821078f625a03eb8b7794c983da0f7793366ab Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 11 May 2018 14:08:16 -0400 Subject: [PATCH 05/47] update std.Buffer API * remove Buffer.appendFormat * remove Buffer.appendByte * remove Buffer.appendByteNTimes Added test to demo what to use instead of the above functions --- std/buffer.zig | 24 ++++-------------------- std/io_test.zig | 18 +++++++++++++++++- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/std/buffer.zig b/std/buffer.zig index 041d891dec374a8ddd1e7b85edc25d07f8af75d5..42fec7f988a3c604d4b0af739c0a2dd6cb3b6a8d 100644 --- a/std/buffer.zig +++ b/std/buffer.zig @@ -99,26 +99,10 @@ pub const Buffer = struct { mem.copy(u8, self.list.toSlice()[old_len..], m); } - // TODO: remove, use OutStream for this - pub fn appendFormat(self: &Buffer, comptime format: []const u8, args: ...) !void { - return fmt.format(self, append, format, args); - } - - // TODO: remove, use OutStream for this pub fn appendByte(self: &Buffer, byte: u8) !void { - return self.appendByteNTimes(byte, 1); - } - - // TODO: remove, use OutStream for this - pub fn appendByteNTimes(self: &Buffer, byte: u8, count: usize) !void { - var prev_size: usize = self.len(); - const new_size = prev_size + count; - try self.resize(new_size); - - var i: usize = prev_size; - while (i < new_size) : (i += 1) { - self.list.items[i] = byte; - } + const old_len = self.len(); + try self.resize(old_len + 1); + self.list.toSlice()[old_len] = byte; } pub fn eql(self: &const Buffer, m: []const u8) bool { @@ -154,7 +138,7 @@ test "simple Buffer" { var buf = try Buffer.init(debug.global_allocator, ""); assert(buf.len() == 0); try buf.append("hello"); - try buf.appendByte(' '); + try buf.append(" "); try buf.append("world"); assert(buf.eql("hello world")); assert(mem.eql(u8, cstr.toSliceConst(buf.toSliceConst().ptr), buf.toSliceConst())); diff --git a/std/io_test.zig b/std/io_test.zig index 89959b7b544f0f08be43e99beb5fd0c8c809c805..5f535567857fc1795aba5eed6da6d19aec1cab64 100644 --- a/std/io_test.zig +++ b/std/io_test.zig @@ -1,6 +1,5 @@ const std = @import("index.zig"); const io = std.io; -const allocator = std.debug.global_allocator; const DefaultPrng = std.rand.DefaultPrng; const assert = std.debug.assert; const mem = std.mem; @@ -8,6 +7,9 @@ const os = std.os; const builtin = @import("builtin"); test "write a file, read it, then delete it" { + var raw_bytes: [200 * 1024]u8 = undefined; + var allocator = &std.heap.FixedBufferAllocator.init(raw_bytes[0..]).allocator; + var data: [1024]u8 = undefined; var prng = DefaultPrng.init(1234); prng.random.bytes(data[0..]); @@ -44,3 +46,17 @@ test "write a file, read it, then delete it" { } try os.deleteFile(allocator, tmp_file_name); } + +test "BufferOutStream" { + var bytes: [100]u8 = undefined; + var allocator = &std.heap.FixedBufferAllocator.init(bytes[0..]).allocator; + + var buffer = try std.Buffer.initSize(allocator, 0); + var buf_stream = &std.io.BufferOutStream.init(&buffer).stream; + + const x: i32 = 42; + const y: i32 = 1234; + try buf_stream.print("x: {}\ny: {}\n", x, y); + + assert(mem.eql(u8, buffer.toSlice(), "x: 42\ny: 1234\n")); +} -- 2.54.0 From 277b9cf8788f340f387e63029ad9fc12664cafff Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 11 May 2018 22:41:44 -0400 Subject: [PATCH 06/47] fix comptime code modification of global const closes #1008 --- src/ir.cpp | 7 ++++++- test/cases/eval.zig | 17 +++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/ir.cpp b/src/ir.cpp index 1e6a7d7b8bff2367c2b2632198213dc8726cd652..c251f3032090485bd50d48379de0e0583cb84bc6 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -8686,6 +8686,10 @@ static void copy_const_val(ConstExprValue *dest, ConstExprValue *src, bool same_ *dest = *src; if (!same_global_refs) { dest->global_refs = global_refs; + if (dest->type->id == TypeTableEntryIdStruct) { + dest->data.x_struct.fields = allocate_nonzero(dest->type->data.structure.src_field_count); + memcpy(dest->data.x_struct.fields, src->data.x_struct.fields, sizeof(ConstExprValue) * dest->type->data.structure.src_field_count); + } } } @@ -11670,7 +11674,8 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc if (var->mem_slot_index != SIZE_MAX) { assert(var->mem_slot_index < ira->exec_context.mem_slot_count); ConstExprValue *mem_slot = &ira->exec_context.mem_slot_list[var->mem_slot_index]; - *mem_slot = casted_init_value->value; + copy_const_val(mem_slot, &casted_init_value->value, + !is_comptime_var || var->gen_is_const); if (is_comptime_var || (var_class_requires_const && var->gen_is_const)) { ir_build_const_from(ira, &decl_var_instruction->base); diff --git a/test/cases/eval.zig b/test/cases/eval.zig index 364db5e152d6d64ad440c52369d26de48c92da91..1ed30872e047ff79cc6e65c7f600d43161fd1acc 100644 --- a/test/cases/eval.zig +++ b/test/cases/eval.zig @@ -536,3 +536,20 @@ test "runtime 128 bit integer division" { var c = a / b; assert(c == 15231399999); } + +pub const Info = struct { + version: u8, +}; + +pub const diamond_info = Info { + .version = 0, +}; + +test "comptime modification of const struct field" { + comptime { + var res = diamond_info; + res.version = 1; + assert(diamond_info.version == 0); + assert(res.version == 1); + } +} -- 2.54.0 From 4277762b742216d4dd44bfe7490947e69527fbc7 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 11 May 2018 23:04:41 -0400 Subject: [PATCH 07/47] fix windows build system broken by 6e821078f625a03eb8b7794c983da0f7793366ab --- std/os/child_process.zig | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/std/os/child_process.zig b/std/os/child_process.zig index 8bb8b2d7e757414d850bddacc50678eb392519ce..ebc8a38cd1c44d003f606b8c58018975f361713c 100644 --- a/std/os/child_process.zig +++ b/std/os/child_process.zig @@ -650,6 +650,8 @@ fn windowsCreateCommandLine(allocator: &mem.Allocator, argv: []const []const u8) var buf = try Buffer.initSize(allocator, 0); defer buf.deinit(); + var buf_stream = &io.BufferOutStream.init(&buf).stream; + for (argv) |arg, arg_i| { if (arg_i != 0) try buf.appendByte(' '); @@ -663,18 +665,18 @@ fn windowsCreateCommandLine(allocator: &mem.Allocator, argv: []const []const u8) switch (byte) { '\\' => backslash_count += 1, '"' => { - try buf.appendByteNTimes('\\', backslash_count * 2 + 1); + try buf_stream.writeByteNTimes('\\', backslash_count * 2 + 1); try buf.appendByte('"'); backslash_count = 0; }, else => { - try buf.appendByteNTimes('\\', backslash_count); + try buf_stream.writeByteNTimes('\\', backslash_count); try buf.appendByte(byte); backslash_count = 0; }, } } - try buf.appendByteNTimes('\\', backslash_count * 2); + try buf_stream.writeByteNTimes('\\', backslash_count * 2); try buf.appendByte('"'); } -- 2.54.0 From a6ae45145f5814963cfdff4e18c1f984729588b9 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 12 May 2018 17:35:15 -0400 Subject: [PATCH 08/47] add @newStackCall builtin function See #1006 --- doc/langref.html.in | 47 +++++++++++++++-- src/all_types.hpp | 7 +++ src/codegen.cpp | 99 ++++++++++++++++++++++++++++++++++- src/ir.cpp | 66 +++++++++++++++++++---- src/target.cpp | 62 ++++++++++++++++++++++ src/target.hpp | 2 + test/behavior.zig | 5 +- test/cases/new_stack_call.zig | 26 +++++++++ 8 files changed, 298 insertions(+), 16 deletions(-) create mode 100644 test/cases/new_stack_call.zig diff --git a/doc/langref.html.in b/doc/langref.html.in index b867ff0b3523dba8825bbb3a683420e9033227b2..4ae98abbd2ae0f8843fb874f9694fa3d34267235 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -4485,17 +4485,58 @@ mem.set(u8, dest, c); If no overflow or underflow occurs, returns false.

{#header_close#} + {#header_open|@newStackCall#} +
@newStackCall(new_stack: []u8, function: var, args: ...) -> var
+

+ This calls a function, in the same way that invoking an expression with parentheses does. However, + instead of using the same stack as the caller, the function uses the stack provided in the new_stack + parameter. +

+ {#code_begin|test#} +const std = @import("std"); +const assert = std.debug.assert; + +var new_stack_bytes: [1024]u8 = undefined; + +test "calling a function with a new stack" { + const arg = 1234; + + const a = @newStackCall(new_stack_bytes[0..512], targetFunction, arg); + const b = @newStackCall(new_stack_bytes[512..], targetFunction, arg); + _ = targetFunction(arg); + + assert(arg == 1234); + assert(a < b); +} + +fn targetFunction(x: i32) usize { + assert(x == 1234); + + var local_variable: i32 = 42; + const ptr = &local_variable; + *ptr += 1; + + assert(local_variable == 43); + return @ptrToInt(ptr); +} + {#code_end#} + {#header_close#} {#header_open|@noInlineCall#}
@noInlineCall(function: var, args: ...) -> var

This calls a function, in the same way that invoking an expression with parentheses does:

-
const assert = @import("std").debug.assert;
+      {#code_begin|test#}
+const assert = @import("std").debug.assert;
+
 test "noinline function call" {
     assert(@noInlineCall(add, 3, 9) == 12);
 }
 
-fn add(a: i32, b: i32) -> i32 { a + b }
+fn add(a: i32, b: i32) i32 { + return a + b; +} + {#code_end#}

Unlike a normal function call, however, @noInlineCall guarantees that the call will not be inlined. If the call must be inlined, a compile error is emitted. @@ -6451,7 +6492,7 @@ hljs.registerLanguage("zig", function(t) { a = t.IR + "\\s*\\(", c = { keyword: "const align var extern stdcallcc nakedcc volatile export pub noalias inline struct packed enum union break return try catch test continue unreachable comptime and or asm defer errdefer if else switch while for fn use bool f32 f64 void type noreturn error i8 u8 i16 u16 i32 u32 i64 u64 isize usize i8w u8w i16w i32w u32w i64w u64w isizew usizew c_short c_ushort c_int c_uint c_long c_ulong c_longlong c_ulonglong", - built_in: "atomicLoad breakpoint returnAddress frameAddress fieldParentPtr setFloatMode IntType OpaqueType compileError compileLog setCold setRuntimeSafety setEvalBranchQuota offsetOf memcpy inlineCall setGlobalLinkage setGlobalSection divTrunc divFloor enumTagName intToPtr ptrToInt panic canImplicitCast ptrCast bitCast rem mod memset sizeOf alignOf alignCast maxValue minValue memberCount memberName memberType typeOf addWithOverflow subWithOverflow mulWithOverflow shlWithOverflow shlExact shrExact cInclude cDefine cUndef ctz clz import cImport errorName embedFile cmpxchgStrong cmpxchgWeak fence divExact truncate atomicRmw sqrt field typeInfo", + built_in: "atomicLoad breakpoint returnAddress frameAddress fieldParentPtr setFloatMode IntType OpaqueType compileError compileLog setCold setRuntimeSafety setEvalBranchQuota offsetOf memcpy inlineCall setGlobalLinkage setGlobalSection divTrunc divFloor enumTagName intToPtr ptrToInt panic canImplicitCast ptrCast bitCast rem mod memset sizeOf alignOf alignCast maxValue minValue memberCount memberName memberType typeOf addWithOverflow subWithOverflow mulWithOverflow shlWithOverflow shlExact shrExact cInclude cDefine cUndef ctz clz import cImport errorName embedFile cmpxchgStrong cmpxchgWeak fence divExact truncate atomicRmw sqrt field typeInfo newStackCall", literal: "true false null undefined" }, n = [e, t.CLCM, t.CBCM, s, r]; diff --git a/src/all_types.hpp b/src/all_types.hpp index c1c6c9a1a598d6369cce9338b383bbc25b1440d7..dc61c8235f4753f712e7876f33ad5080d0c828c7 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -1340,6 +1340,7 @@ enum BuiltinFnId { BuiltinFnIdOffsetOf, BuiltinFnIdInlineCall, BuiltinFnIdNoInlineCall, + BuiltinFnIdNewStackCall, BuiltinFnIdTypeId, BuiltinFnIdShlExact, BuiltinFnIdShrExact, @@ -1656,8 +1657,13 @@ struct CodeGen { LLVMValueRef coro_alloc_helper_fn_val; LLVMValueRef merge_err_ret_traces_fn_val; LLVMValueRef add_error_return_trace_addr_fn_val; + LLVMValueRef stacksave_fn_val; + LLVMValueRef stackrestore_fn_val; + LLVMValueRef write_register_fn_val; bool error_during_imports; + LLVMValueRef sp_md_node; + const char **clang_argv; size_t clang_argv_len; ZigList lib_dirs; @@ -2280,6 +2286,7 @@ struct IrInstructionCall { bool is_async; IrInstruction *async_allocator; + IrInstruction *new_stack; }; struct IrInstructionConst { diff --git a/src/codegen.cpp b/src/codegen.cpp index 4e58f86d4b52c439d81a2737a0a1e2abfa1880fd..f1e102392a23f72e2efe71b38ce0afd19d8a8119 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -938,6 +938,53 @@ static LLVMValueRef get_memcpy_fn_val(CodeGen *g) { return g->memcpy_fn_val; } +static LLVMValueRef get_stacksave_fn_val(CodeGen *g) { + if (g->stacksave_fn_val) + return g->stacksave_fn_val; + + // declare i8* @llvm.stacksave() + + LLVMTypeRef fn_type = LLVMFunctionType(LLVMPointerType(LLVMInt8Type(), 0), nullptr, 0, false); + g->stacksave_fn_val = LLVMAddFunction(g->module, "llvm.stacksave", fn_type); + assert(LLVMGetIntrinsicID(g->stacksave_fn_val)); + + return g->stacksave_fn_val; +} + +static LLVMValueRef get_stackrestore_fn_val(CodeGen *g) { + if (g->stackrestore_fn_val) + return g->stackrestore_fn_val; + + // declare void @llvm.stackrestore(i8* %ptr) + + LLVMTypeRef param_type = LLVMPointerType(LLVMInt8Type(), 0); + LLVMTypeRef fn_type = LLVMFunctionType(LLVMVoidType(), ¶m_type, 1, false); + g->stackrestore_fn_val = LLVMAddFunction(g->module, "llvm.stackrestore", fn_type); + assert(LLVMGetIntrinsicID(g->stackrestore_fn_val)); + + return g->stackrestore_fn_val; +} + +static LLVMValueRef get_write_register_fn_val(CodeGen *g) { + if (g->write_register_fn_val) + return g->write_register_fn_val; + + // declare void @llvm.write_register.i64(metadata, i64 @value) + // !0 = !{!"sp\00"} + + LLVMTypeRef param_types[] = { + LLVMMetadataTypeInContext(LLVMGetGlobalContext()), + LLVMIntType(g->pointer_size_bytes * 8), + }; + + LLVMTypeRef fn_type = LLVMFunctionType(LLVMVoidType(), param_types, 2, false); + Buf *name = buf_sprintf("llvm.write_register.i%d", g->pointer_size_bytes * 8); + g->write_register_fn_val = LLVMAddFunction(g->module, buf_ptr(name), fn_type); + assert(LLVMGetIntrinsicID(g->write_register_fn_val)); + + return g->write_register_fn_val; +} + static LLVMValueRef get_coro_destroy_fn_val(CodeGen *g) { if (g->coro_destroy_fn_val) return g->coro_destroy_fn_val; @@ -2901,6 +2948,38 @@ static size_t get_async_err_code_arg_index(CodeGen *g, FnTypeId *fn_type_id) { return 1 + get_async_allocator_arg_index(g, fn_type_id); } + +static LLVMValueRef get_new_stack_addr(CodeGen *g, LLVMValueRef new_stack) { + LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, new_stack, (unsigned)slice_ptr_index, ""); + LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, new_stack, (unsigned)slice_len_index, ""); + + LLVMValueRef ptr_value = gen_load_untyped(g, ptr_field_ptr, 0, false, ""); + LLVMValueRef len_value = gen_load_untyped(g, len_field_ptr, 0, false, ""); + + LLVMValueRef ptr_addr = LLVMBuildPtrToInt(g->builder, ptr_value, LLVMTypeOf(len_value), ""); + LLVMValueRef end_addr = LLVMBuildNUWAdd(g->builder, ptr_addr, len_value, ""); + LLVMValueRef align_amt = LLVMConstInt(LLVMTypeOf(end_addr), get_abi_alignment(g, g->builtin_types.entry_usize), false); + LLVMValueRef align_adj = LLVMBuildURem(g->builder, end_addr, align_amt, ""); + return LLVMBuildNUWSub(g->builder, end_addr, align_adj, ""); +} + +static void gen_set_stack_pointer(CodeGen *g, LLVMValueRef aligned_end_addr) { + LLVMValueRef write_register_fn_val = get_write_register_fn_val(g); + + if (g->sp_md_node == nullptr) { + Buf *sp_reg_name = buf_create_from_str(arch_stack_pointer_register_name(&g->zig_target.arch)); + LLVMValueRef str_node = LLVMMDString(buf_ptr(sp_reg_name), buf_len(sp_reg_name) + 1); + g->sp_md_node = LLVMMDNode(&str_node, 1); + } + + LLVMValueRef params[] = { + g->sp_md_node, + aligned_end_addr, + }; + + LLVMBuildCall(g->builder, write_register_fn_val, params, 2, ""); +} + static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstructionCall *instruction) { LLVMValueRef fn_val; TypeTableEntry *fn_type; @@ -2967,8 +3046,23 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr } LLVMCallConv llvm_cc = get_llvm_cc(g, fn_type->data.fn.fn_type_id.cc); - LLVMValueRef result = ZigLLVMBuildCall(g->builder, fn_val, - gen_param_values, (unsigned)gen_param_index, llvm_cc, fn_inline, ""); + LLVMValueRef result; + + if (instruction->new_stack == nullptr) { + result = ZigLLVMBuildCall(g->builder, fn_val, + gen_param_values, (unsigned)gen_param_index, llvm_cc, fn_inline, ""); + } else { + LLVMValueRef stacksave_fn_val = get_stacksave_fn_val(g); + LLVMValueRef stackrestore_fn_val = get_stackrestore_fn_val(g); + + LLVMValueRef new_stack_addr = get_new_stack_addr(g, ir_llvm_value(g, instruction->new_stack)); + LLVMValueRef old_stack_ref = LLVMBuildCall(g->builder, stacksave_fn_val, nullptr, 0, ""); + gen_set_stack_pointer(g, new_stack_addr); + result = ZigLLVMBuildCall(g->builder, fn_val, + gen_param_values, (unsigned)gen_param_index, llvm_cc, fn_inline, ""); + LLVMBuildCall(g->builder, stackrestore_fn_val, &old_stack_ref, 1, ""); + } + for (size_t param_i = 0; param_i < fn_type_id->param_count; param_i += 1) { FnGenParamInfo *gen_info = &fn_type->data.fn.gen_param_info[param_i]; @@ -6171,6 +6265,7 @@ static void define_builtin_fns(CodeGen *g) { create_builtin_fn(g, BuiltinFnIdSqrt, "sqrt", 2); create_builtin_fn(g, BuiltinFnIdInlineCall, "inlineCall", SIZE_MAX); create_builtin_fn(g, BuiltinFnIdNoInlineCall, "noInlineCall", SIZE_MAX); + create_builtin_fn(g, BuiltinFnIdNewStackCall, "newStackCall", SIZE_MAX); create_builtin_fn(g, BuiltinFnIdTypeId, "typeId", 1); create_builtin_fn(g, BuiltinFnIdShlExact, "shlExact", 2); create_builtin_fn(g, BuiltinFnIdShrExact, "shrExact", 2); diff --git a/src/ir.cpp b/src/ir.cpp index c251f3032090485bd50d48379de0e0583cb84bc6..7bc837d9083eefbb923527fffab2d23b000b0ad0 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -1102,7 +1102,8 @@ static IrInstruction *ir_build_union_field_ptr_from(IrBuilder *irb, IrInstructio static IrInstruction *ir_build_call(IrBuilder *irb, Scope *scope, AstNode *source_node, FnTableEntry *fn_entry, IrInstruction *fn_ref, size_t arg_count, IrInstruction **args, - bool is_comptime, FnInline fn_inline, bool is_async, IrInstruction *async_allocator) + bool is_comptime, FnInline fn_inline, bool is_async, IrInstruction *async_allocator, + IrInstruction *new_stack) { IrInstructionCall *call_instruction = ir_build_instruction(irb, scope, source_node); call_instruction->fn_entry = fn_entry; @@ -1113,6 +1114,7 @@ static IrInstruction *ir_build_call(IrBuilder *irb, Scope *scope, AstNode *sourc call_instruction->arg_count = arg_count; call_instruction->is_async = is_async; call_instruction->async_allocator = async_allocator; + call_instruction->new_stack = new_stack; if (fn_ref) ir_ref_instruction(fn_ref, irb->current_basic_block); @@ -1120,16 +1122,19 @@ static IrInstruction *ir_build_call(IrBuilder *irb, Scope *scope, AstNode *sourc ir_ref_instruction(args[i], irb->current_basic_block); if (async_allocator) ir_ref_instruction(async_allocator, irb->current_basic_block); + if (new_stack != nullptr) + ir_ref_instruction(new_stack, irb->current_basic_block); return &call_instruction->base; } static IrInstruction *ir_build_call_from(IrBuilder *irb, IrInstruction *old_instruction, FnTableEntry *fn_entry, IrInstruction *fn_ref, size_t arg_count, IrInstruction **args, - bool is_comptime, FnInline fn_inline, bool is_async, IrInstruction *async_allocator) + bool is_comptime, FnInline fn_inline, bool is_async, IrInstruction *async_allocator, + IrInstruction *new_stack) { IrInstruction *new_instruction = ir_build_call(irb, old_instruction->scope, - old_instruction->source_node, fn_entry, fn_ref, arg_count, args, is_comptime, fn_inline, is_async, async_allocator); + old_instruction->source_node, fn_entry, fn_ref, arg_count, args, is_comptime, fn_inline, is_async, async_allocator, new_stack); ir_link_new_instruction(new_instruction, old_instruction); return new_instruction; } @@ -4303,7 +4308,37 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo } FnInline fn_inline = (builtin_fn->id == BuiltinFnIdInlineCall) ? FnInlineAlways : FnInlineNever; - IrInstruction *call = ir_build_call(irb, scope, node, nullptr, fn_ref, arg_count, args, false, fn_inline, false, nullptr); + IrInstruction *call = ir_build_call(irb, scope, node, nullptr, fn_ref, arg_count, args, false, fn_inline, false, nullptr, nullptr); + return ir_lval_wrap(irb, scope, call, lval); + } + case BuiltinFnIdNewStackCall: + { + if (node->data.fn_call_expr.params.length == 0) { + add_node_error(irb->codegen, node, buf_sprintf("expected at least 1 argument, found 0")); + return irb->codegen->invalid_instruction; + } + + AstNode *new_stack_node = node->data.fn_call_expr.params.at(0); + IrInstruction *new_stack = ir_gen_node(irb, new_stack_node, scope); + if (new_stack == irb->codegen->invalid_instruction) + return new_stack; + + AstNode *fn_ref_node = node->data.fn_call_expr.params.at(1); + IrInstruction *fn_ref = ir_gen_node(irb, fn_ref_node, scope); + if (fn_ref == irb->codegen->invalid_instruction) + return fn_ref; + + size_t arg_count = node->data.fn_call_expr.params.length - 2; + + IrInstruction **args = allocate(arg_count); + for (size_t i = 0; i < arg_count; i += 1) { + AstNode *arg_node = node->data.fn_call_expr.params.at(i + 2); + args[i] = ir_gen_node(irb, arg_node, scope); + if (args[i] == irb->codegen->invalid_instruction) + return args[i]; + } + + IrInstruction *call = ir_build_call(irb, scope, node, nullptr, fn_ref, arg_count, args, false, FnInlineAuto, false, nullptr, new_stack); return ir_lval_wrap(irb, scope, call, lval); } case BuiltinFnIdTypeId: @@ -4513,7 +4548,7 @@ static IrInstruction *ir_gen_fn_call(IrBuilder *irb, Scope *scope, AstNode *node } } - IrInstruction *fn_call = ir_build_call(irb, scope, node, nullptr, fn_ref, arg_count, args, false, FnInlineAuto, is_async, async_allocator); + IrInstruction *fn_call = ir_build_call(irb, scope, node, nullptr, fn_ref, arg_count, args, false, FnInlineAuto, is_async, async_allocator, nullptr); return ir_lval_wrap(irb, scope, fn_call, lval); } @@ -6825,7 +6860,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec IrInstruction **args = allocate(arg_count); args[0] = implicit_allocator_ptr; // self args[1] = mem_slice; // old_mem - ir_build_call(irb, scope, node, nullptr, free_fn, arg_count, args, false, FnInlineAuto, false, nullptr); + ir_build_call(irb, scope, node, nullptr, free_fn, arg_count, args, false, FnInlineAuto, false, nullptr, nullptr); IrBasicBlock *resume_block = ir_create_basic_block(irb, scope, "Resume"); ir_build_cond_br(irb, scope, node, resume_awaiter, resume_block, irb->exec->coro_suspend_block, const_bool_false); @@ -11992,7 +12027,7 @@ static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCall *c TypeTableEntry *async_return_type = get_error_union_type(ira->codegen, alloc_fn_error_set_type, promise_type); IrInstruction *result = ir_build_call(&ira->new_irb, call_instruction->base.scope, call_instruction->base.source_node, - fn_entry, fn_ref, arg_count, casted_args, false, FnInlineAuto, true, async_allocator_inst); + fn_entry, fn_ref, arg_count, casted_args, false, FnInlineAuto, true, async_allocator_inst, nullptr); result->value.type = async_return_type; return result; } @@ -12362,6 +12397,19 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal return ir_finish_anal(ira, return_type); } + IrInstruction *casted_new_stack = nullptr; + if (call_instruction->new_stack != nullptr) { + TypeTableEntry *u8_ptr = get_pointer_to_type(ira->codegen, ira->codegen->builtin_types.entry_u8, false); + TypeTableEntry *u8_slice = get_slice_type(ira->codegen, u8_ptr); + IrInstruction *new_stack = call_instruction->new_stack->other; + if (type_is_invalid(new_stack->value.type)) + return ira->codegen->builtin_types.entry_invalid; + + casted_new_stack = ir_implicit_cast(ira, new_stack, u8_slice); + if (type_is_invalid(casted_new_stack->value.type)) + return ira->codegen->builtin_types.entry_invalid; + } + if (fn_type->data.fn.is_generic) { if (!fn_entry) { ir_add_error(ira, call_instruction->fn_ref, @@ -12588,7 +12636,7 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal assert(async_allocator_inst == nullptr); IrInstruction *new_call_instruction = ir_build_call_from(&ira->new_irb, &call_instruction->base, impl_fn, nullptr, impl_param_count, casted_args, false, fn_inline, - call_instruction->is_async, nullptr); + call_instruction->is_async, nullptr, casted_new_stack); ir_add_alloca(ira, new_call_instruction, return_type); @@ -12679,7 +12727,7 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal IrInstruction *new_call_instruction = ir_build_call_from(&ira->new_irb, &call_instruction->base, - fn_entry, fn_ref, call_param_count, casted_args, false, fn_inline, false, nullptr); + fn_entry, fn_ref, call_param_count, casted_args, false, fn_inline, false, nullptr, casted_new_stack); ir_add_alloca(ira, new_call_instruction, return_type); return ir_finish_anal(ira, return_type); diff --git a/src/target.cpp b/src/target.cpp index 5008b51a09d4cc057f01fd2f47d2aa4b7c1dad83..57970888fcee76c64e4172d102b750897ec6df17 100644 --- a/src/target.cpp +++ b/src/target.cpp @@ -896,3 +896,65 @@ bool target_can_exec(const ZigTarget *host_target, const ZigTarget *guest_target return false; } + +const char *arch_stack_pointer_register_name(const ArchType *arch) { + switch (arch->arch) { + case ZigLLVM_UnknownArch: + zig_unreachable(); + case ZigLLVM_x86: + return "sp"; + case ZigLLVM_x86_64: + return "rsp"; + + case ZigLLVM_aarch64: + case ZigLLVM_arm: + case ZigLLVM_thumb: + case ZigLLVM_aarch64_be: + case ZigLLVM_amdgcn: + case ZigLLVM_amdil: + case ZigLLVM_amdil64: + case ZigLLVM_armeb: + case ZigLLVM_arc: + case ZigLLVM_avr: + case ZigLLVM_bpfeb: + case ZigLLVM_bpfel: + case ZigLLVM_hexagon: + case ZigLLVM_lanai: + case ZigLLVM_hsail: + case ZigLLVM_hsail64: + case ZigLLVM_kalimba: + case ZigLLVM_le32: + case ZigLLVM_le64: + case ZigLLVM_mips: + case ZigLLVM_mips64: + case ZigLLVM_mips64el: + case ZigLLVM_mipsel: + case ZigLLVM_msp430: + case ZigLLVM_nios2: + case ZigLLVM_nvptx: + case ZigLLVM_nvptx64: + case ZigLLVM_ppc64le: + case ZigLLVM_r600: + case ZigLLVM_renderscript32: + case ZigLLVM_renderscript64: + case ZigLLVM_riscv32: + case ZigLLVM_riscv64: + case ZigLLVM_shave: + case ZigLLVM_sparc: + case ZigLLVM_sparcel: + case ZigLLVM_sparcv9: + case ZigLLVM_spir: + case ZigLLVM_spir64: + case ZigLLVM_systemz: + case ZigLLVM_tce: + case ZigLLVM_tcele: + case ZigLLVM_thumbeb: + case ZigLLVM_wasm32: + case ZigLLVM_wasm64: + case ZigLLVM_xcore: + case ZigLLVM_ppc: + case ZigLLVM_ppc64: + zig_panic("TODO populate this table with stack pointer register name for this CPU architecture"); + } + zig_unreachable(); +} diff --git a/src/target.hpp b/src/target.hpp index 614b0627d522bff8c6c3537a137805e0b8b8114b..5a118f6d8d3f1c7a3162a8c64c520ff180139883 100644 --- a/src/target.hpp +++ b/src/target.hpp @@ -77,6 +77,8 @@ size_t target_arch_count(void); const ArchType *get_target_arch(size_t index); void get_arch_name(char *out_str, const ArchType *arch); +const char *arch_stack_pointer_register_name(const ArchType *arch); + size_t target_vendor_count(void); ZigLLVM_VendorType get_target_vendor(size_t index); diff --git a/test/behavior.zig b/test/behavior.zig index d700faaebc75f341fdde96af868c595821988ab9..fbec60f648d2dcd253f7e603fc53b91b26f9a9cb 100644 --- a/test/behavior.zig +++ b/test/behavior.zig @@ -23,6 +23,7 @@ comptime { _ = @import("cases/eval.zig"); _ = @import("cases/field_parent_ptr.zig"); _ = @import("cases/fn.zig"); + _ = @import("cases/fn_in_struct_in_comptime.zig"); _ = @import("cases/for.zig"); _ = @import("cases/generics.zig"); _ = @import("cases/if.zig"); @@ -32,11 +33,11 @@ comptime { _ = @import("cases/math.zig"); _ = @import("cases/misc.zig"); _ = @import("cases/namespace_depends_on_compile_var/index.zig"); + _ = @import("cases/new_stack_call.zig"); _ = @import("cases/null.zig"); _ = @import("cases/pub_enum/index.zig"); _ = @import("cases/ref_var_in_if_after_if_2nd_switch_prong.zig"); _ = @import("cases/reflection.zig"); - _ = @import("cases/type_info.zig"); _ = @import("cases/sizeof_and_typeof.zig"); _ = @import("cases/slice.zig"); _ = @import("cases/struct.zig"); @@ -48,10 +49,10 @@ comptime { _ = @import("cases/syntax.zig"); _ = @import("cases/this.zig"); _ = @import("cases/try.zig"); + _ = @import("cases/type_info.zig"); _ = @import("cases/undefined.zig"); _ = @import("cases/union.zig"); _ = @import("cases/var_args.zig"); _ = @import("cases/void.zig"); _ = @import("cases/while.zig"); - _ = @import("cases/fn_in_struct_in_comptime.zig"); } diff --git a/test/cases/new_stack_call.zig b/test/cases/new_stack_call.zig new file mode 100644 index 0000000000000000000000000000000000000000..ea9f0c914fe11257d61f0f6e43a7907ffd7a2a45 --- /dev/null +++ b/test/cases/new_stack_call.zig @@ -0,0 +1,26 @@ +const std = @import("std"); +const assert = std.debug.assert; + +var new_stack_bytes: [1024]u8 = undefined; + +test "calling a function with a new stack" { + const arg = 1234; + + const a = @newStackCall(new_stack_bytes[0..512], targetFunction, arg); + const b = @newStackCall(new_stack_bytes[512..], targetFunction, arg); + _ = targetFunction(arg); + + assert(arg == 1234); + assert(a < b); +} + +fn targetFunction(x: i32) usize { + assert(x == 1234); + + var local_variable: i32 = 42; + const ptr = &local_variable; + *ptr += 1; + + assert(local_variable == 43); + return @ptrToInt(ptr); +} -- 2.54.0 From 911cbf57cd10159176950285feb9ee14fb88a803 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 12 May 2018 19:03:39 -0400 Subject: [PATCH 09/47] recursive render top level decl --- std/zig/render.zig | 42 +++++++++++++++++++----------------------- 1 file changed, 19 insertions(+), 23 deletions(-) diff --git a/std/zig/render.zig b/std/zig/render.zig index cced30cd60ee77d98c5feceb677fb11ff6cb9c51..c7a08a11fd95fea7bbf45281f7bb5f7cd9ef10b6 100644 --- a/std/zig/render.zig +++ b/std/zig/render.zig @@ -21,32 +21,28 @@ const RenderState = union(enum) { const indent_delta = 4; pub fn render(allocator: &mem.Allocator, stream: var, tree: &ast.Tree) !void { + var it = tree.root_node.decls.iterator(0); + while (it.next()) |decl| { + try renderTopLevelDecl(allocator, stream, tree, *decl); + if (it.peek()) |next_decl| { + const n = if (nodeLineOffset(tree, *decl, *next_decl) >= 2) u8(2) else u8(1); + try stream.writeByteNTimes('\n', n); + } + } + try stream.write("\n"); +} + +fn nodeLineOffset(tree: &ast.Tree, a: &ast.Node, b: &ast.Node) usize { + const a_last_token = tree.tokens.at(a.lastToken()); + const loc = tree.tokenLocation(a_last_token.end, b.firstToken()); + return loc.line; +} + +fn renderTopLevelDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, decl_ptr: &ast.Node) !void { var stack = std.ArrayList(RenderState).init(allocator); defer stack.deinit(); - { - try stack.append(RenderState { .Text = "\n"}); - - var i = tree.root_node.decls.len; - while (i != 0) { - i -= 1; - const decl = *tree.root_node.decls.at(i); - try stack.append(RenderState {.TopLevelDecl = decl}); - if (i != 0) { - try stack.append(RenderState { - .Text = blk: { - const prev_node = *tree.root_node.decls.at(i - 1); - const prev_node_last_token = tree.tokens.at(prev_node.lastToken()); - const loc = tree.tokenLocation(prev_node_last_token.end, decl.firstToken()); - if (loc.line >= 2) { - break :blk "\n\n"; - } - break :blk "\n"; - }, - }); - } - } - } + try stack.append(RenderState {.TopLevelDecl = decl_ptr}); var indent: usize = 0; while (stack.popOrNull()) |state| { -- 2.54.0 From 7cdc9d98c7134be5edd18eb6f94dd8cfc55bb764 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 12 May 2018 23:06:54 -0400 Subject: [PATCH 10/47] refactor std.zig.render to be recursive See #1006 --- std/zig/render.zig | 2211 ++++++++++++++++++++++---------------------- 1 file changed, 1084 insertions(+), 1127 deletions(-) diff --git a/std/zig/render.zig b/std/zig/render.zig index c7a08a11fd95fea7bbf45281f7bb5f7cd9ef10b6..13ef4607f49e28028749f984a68c76215b140d54 100644 --- a/std/zig/render.zig +++ b/std/zig/render.zig @@ -1,29 +1,23 @@ const std = @import("../index.zig"); +const builtin = @import("builtin"); const assert = std.debug.assert; const mem = std.mem; const ast = std.zig.ast; const Token = std.zig.Token; -const RenderState = union(enum) { - TopLevelDecl: &ast.Node, - ParamDecl: &ast.Node, - Text: []const u8, - Expression: &ast.Node, - VarDecl: &ast.Node.VarDecl, - Statement: &ast.Node, - PrintIndent, - Indent: usize, - MaybeSemiColon: &ast.Node, - Token: ast.TokenIndex, - NonBreakToken: ast.TokenIndex, -}; - const indent_delta = 4; -pub fn render(allocator: &mem.Allocator, stream: var, tree: &ast.Tree) !void { +pub const Error = error { + /// Ran out of memory allocating call stack frames to complete rendering. + OutOfMemory, +}; + +pub fn render(allocator: &mem.Allocator, stream: var, tree: &ast.Tree) (@typeOf(stream).Child.Error || Error)!void { + comptime assert(@typeId(@typeOf(stream)) == builtin.TypeId.Pointer); + var it = tree.root_node.decls.iterator(0); while (it.next()) |decl| { - try renderTopLevelDecl(allocator, stream, tree, *decl); + try renderTopLevelDecl(allocator, stream, tree, 0, *decl); if (it.peek()) |next_decl| { const n = if (nodeLineOffset(tree, *decl, *next_decl) >= 2) u8(2) else u8(1); try stream.writeByteNTimes('\n', n); @@ -38,1202 +32,1165 @@ fn nodeLineOffset(tree: &ast.Tree, a: &ast.Node, b: &ast.Node) usize { return loc.line; } -fn renderTopLevelDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, decl_ptr: &ast.Node) !void { - var stack = std.ArrayList(RenderState).init(allocator); - defer stack.deinit(); - - try stack.append(RenderState {.TopLevelDecl = decl_ptr}); - - var indent: usize = 0; - while (stack.popOrNull()) |state| { - switch (state) { - RenderState.TopLevelDecl => |decl| { - switch (decl.id) { - ast.Node.Id.FnProto => { - const fn_proto = @fieldParentPtr(ast.Node.FnProto, "base", decl); - try renderComments(tree, stream, fn_proto, indent); - - if (fn_proto.body_node) |body_node| { - stack.append(RenderState { .Expression = body_node}) catch unreachable; - try stack.append(RenderState { .Text = " "}); - } else { - stack.append(RenderState { .Text = ";" }) catch unreachable; - } +fn renderTopLevelDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent: usize, decl: &ast.Node) (@typeOf(stream).Child.Error || Error)!void { + switch (decl.id) { + ast.Node.Id.FnProto => { + const fn_proto = @fieldParentPtr(ast.Node.FnProto, "base", decl); - try stack.append(RenderState { .Expression = decl }); - }, - ast.Node.Id.Use => { - const use_decl = @fieldParentPtr(ast.Node.Use, "base", decl); - if (use_decl.visib_token) |visib_token| { - try stream.print("{} ", tree.tokenSlice(visib_token)); - } - try stream.print("use "); - try stack.append(RenderState { .Text = ";" }); - try stack.append(RenderState { .Expression = use_decl.expr }); - }, - ast.Node.Id.VarDecl => { - const var_decl = @fieldParentPtr(ast.Node.VarDecl, "base", decl); - try renderComments(tree, stream, var_decl, indent); - try stack.append(RenderState { .VarDecl = var_decl}); - }, - ast.Node.Id.TestDecl => { - const test_decl = @fieldParentPtr(ast.Node.TestDecl, "base", decl); - try renderComments(tree, stream, test_decl, indent); - try stream.print("test "); - try stack.append(RenderState { .Expression = test_decl.body_node }); - try stack.append(RenderState { .Text = " " }); - try stack.append(RenderState { .Expression = test_decl.name }); - }, - ast.Node.Id.StructField => { - const field = @fieldParentPtr(ast.Node.StructField, "base", decl); - try renderComments(tree, stream, field, indent); - if (field.visib_token) |visib_token| { - try stream.print("{} ", tree.tokenSlice(visib_token)); - } - try stream.print("{}: ", tree.tokenSlice(field.name_token)); - try stack.append(RenderState { .Token = field.lastToken() + 1 }); - try stack.append(RenderState { .Expression = field.type_expr}); - }, - ast.Node.Id.UnionTag => { - const tag = @fieldParentPtr(ast.Node.UnionTag, "base", decl); - try renderComments(tree, stream, tag, indent); - try stream.print("{}", tree.tokenSlice(tag.name_token)); - - try stack.append(RenderState { .Text = "," }); - - if (tag.value_expr) |value_expr| { - try stack.append(RenderState { .Expression = value_expr }); - try stack.append(RenderState { .Text = " = " }); - } + try renderComments(tree, stream, fn_proto, indent); + try renderExpression(allocator, stream, tree, indent, decl); - if (tag.type_expr) |type_expr| { - try stream.print(": "); - try stack.append(RenderState { .Expression = type_expr}); - } - }, - ast.Node.Id.EnumTag => { - const tag = @fieldParentPtr(ast.Node.EnumTag, "base", decl); - try renderComments(tree, stream, tag, indent); - try stream.print("{}", tree.tokenSlice(tag.name_token)); - - try stack.append(RenderState { .Text = "," }); - if (tag.value) |value| { - try stream.print(" = "); - try stack.append(RenderState { .Expression = value}); - } - }, - ast.Node.Id.ErrorTag => { - const tag = @fieldParentPtr(ast.Node.ErrorTag, "base", decl); - try renderComments(tree, stream, tag, indent); - try stream.print("{}", tree.tokenSlice(tag.name_token)); - }, - ast.Node.Id.Comptime => { - try stack.append(RenderState { .MaybeSemiColon = decl }); - try stack.append(RenderState { .Expression = decl }); - }, - ast.Node.Id.LineComment => { - const line_comment_node = @fieldParentPtr(ast.Node.LineComment, "base", decl); - try stream.write(tree.tokenSlice(line_comment_node.token)); - }, - else => unreachable, - } - }, - - RenderState.VarDecl => |var_decl| { - try stack.append(RenderState { .Token = var_decl.semicolon_token }); - if (var_decl.init_node) |init_node| { - try stack.append(RenderState { .Expression = init_node }); - const text = if (init_node.id == ast.Node.Id.MultilineStringLiteral) " =" else " = "; - try stack.append(RenderState { .Text = text }); - } - if (var_decl.align_node) |align_node| { - try stack.append(RenderState { .Text = ")" }); - try stack.append(RenderState { .Expression = align_node }); - try stack.append(RenderState { .Text = " align(" }); - } - if (var_decl.type_node) |type_node| { - try stack.append(RenderState { .Expression = type_node }); - try stack.append(RenderState { .Text = ": " }); - } - try stack.append(RenderState { .Text = tree.tokenSlice(var_decl.name_token) }); - try stack.append(RenderState { .Text = " " }); - try stack.append(RenderState { .Text = tree.tokenSlice(var_decl.mut_token) }); + if (fn_proto.body_node) |body_node| { + try stream.write(" "); + try renderExpression(allocator, stream, tree, indent, body_node); + } else { + try stream.write(";"); + } + }, + ast.Node.Id.Use => { + const use_decl = @fieldParentPtr(ast.Node.Use, "base", decl); - if (var_decl.comptime_token) |comptime_token| { - try stack.append(RenderState { .Text = " " }); - try stack.append(RenderState { .Text = tree.tokenSlice(comptime_token) }); - } + if (use_decl.visib_token) |visib_token| { + try stream.print("{} ", tree.tokenSlice(visib_token)); + } + try stream.write("use "); + try renderExpression(allocator, stream, tree, indent, use_decl.expr); + try stream.write(";"); + }, + ast.Node.Id.VarDecl => { + const var_decl = @fieldParentPtr(ast.Node.VarDecl, "base", decl); + + try renderComments(tree, stream, var_decl, indent); + try renderVarDecl(allocator, stream, tree, indent, var_decl); + }, + ast.Node.Id.TestDecl => { + const test_decl = @fieldParentPtr(ast.Node.TestDecl, "base", decl); + + try renderComments(tree, stream, test_decl, indent); + try stream.write("test "); + try renderExpression(allocator, stream, tree, indent, test_decl.name); + try stream.write(" "); + try renderExpression(allocator, stream, tree, indent, test_decl.body_node); + }, + ast.Node.Id.StructField => { + const field = @fieldParentPtr(ast.Node.StructField, "base", decl); + + try renderComments(tree, stream, field, indent); + if (field.visib_token) |visib_token| { + try stream.print("{} ", tree.tokenSlice(visib_token)); + } + try stream.print("{}: ", tree.tokenSlice(field.name_token)); + try renderExpression(allocator, stream, tree, indent, field.type_expr); + try renderToken(tree, stream, field.lastToken() + 1, indent, true); + }, + ast.Node.Id.UnionTag => { + const tag = @fieldParentPtr(ast.Node.UnionTag, "base", decl); + + try renderComments(tree, stream, tag, indent); + try stream.print("{}", tree.tokenSlice(tag.name_token)); + + if (tag.type_expr) |type_expr| { + try stream.print(": "); + try renderExpression(allocator, stream, tree, indent, type_expr); + } + + if (tag.value_expr) |value_expr| { + try stream.print(" = "); + try renderExpression(allocator, stream, tree, indent, value_expr); + } + + try stream.write(","); + }, + ast.Node.Id.EnumTag => { + const tag = @fieldParentPtr(ast.Node.EnumTag, "base", decl); + + try renderComments(tree, stream, tag, indent); + try stream.print("{}", tree.tokenSlice(tag.name_token)); + + if (tag.value) |value| { + try stream.print(" = "); + try renderExpression(allocator, stream, tree, indent, value); + } + + try stream.write(","); + }, + ast.Node.Id.ErrorTag => { + const tag = @fieldParentPtr(ast.Node.ErrorTag, "base", decl); - if (var_decl.extern_export_token) |extern_export_token| { - if (var_decl.lib_name != null) { - try stack.append(RenderState { .Text = " " }); - try stack.append(RenderState { .Expression = ??var_decl.lib_name }); + try renderComments(tree, stream, tag, indent); + try stream.print("{}", tree.tokenSlice(tag.name_token)); + }, + ast.Node.Id.Comptime => { + try renderExpression(allocator, stream, tree, indent, decl); + try maybeRenderSemicolon(stream, tree, indent, decl); + }, + ast.Node.Id.LineComment => { + const line_comment_node = @fieldParentPtr(ast.Node.LineComment, "base", decl); + + try stream.write(tree.tokenSlice(line_comment_node.token)); + }, + else => unreachable, + } +} + +fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent: usize, base: &ast.Node) (@typeOf(stream).Child.Error || Error)!void { + switch (base.id) { + ast.Node.Id.Identifier => { + const identifier = @fieldParentPtr(ast.Node.Identifier, "base", base); + try stream.print("{}", tree.tokenSlice(identifier.token)); + }, + ast.Node.Id.Block => { + const block = @fieldParentPtr(ast.Node.Block, "base", base); + if (block.label) |label| { + try stream.print("{}: ", tree.tokenSlice(label)); + } + + if (block.statements.len == 0) { + try stream.write("{}"); + } else { + try stream.write("{\n"); + const block_indent = indent + indent_delta; + + var it = block.statements.iterator(0); + while (it.next()) |statement| { + try stream.writeByteNTimes(' ', block_indent); + try renderStatement(allocator, stream, tree, block_indent, *statement); + + if (it.peek()) |next_statement| { + const n = if (nodeLineOffset(tree, *statement, *next_statement) >= 2) u8(2) else u8(1); + try stream.writeByteNTimes('\n', n); } - try stack.append(RenderState { .Text = " " }); - try stack.append(RenderState { .Text = tree.tokenSlice(extern_export_token) }); } - if (var_decl.visib_token) |visib_token| { - try stack.append(RenderState { .Text = " " }); - try stack.append(RenderState { .Text = tree.tokenSlice(visib_token) }); - } - }, + try stream.write("\n"); + try stream.writeByteNTimes(' ', indent); + try stream.write("}"); + } + }, + ast.Node.Id.Defer => { + const defer_node = @fieldParentPtr(ast.Node.Defer, "base", base); + try stream.print("{} ", tree.tokenSlice(defer_node.defer_token)); + try renderExpression(allocator, stream, tree, indent, defer_node.expr); + }, + ast.Node.Id.Comptime => { + const comptime_node = @fieldParentPtr(ast.Node.Comptime, "base", base); + try stream.print("{} ", tree.tokenSlice(comptime_node.comptime_token)); + try renderExpression(allocator, stream, tree, indent, comptime_node.expr); + }, + ast.Node.Id.AsyncAttribute => { + const async_attr = @fieldParentPtr(ast.Node.AsyncAttribute, "base", base); + try stream.print("{}", tree.tokenSlice(async_attr.async_token)); - RenderState.ParamDecl => |base| { - const param_decl = @fieldParentPtr(ast.Node.ParamDecl, "base", base); - if (param_decl.comptime_token) |comptime_token| { - try stream.print("{} ", tree.tokenSlice(comptime_token)); - } - if (param_decl.noalias_token) |noalias_token| { - try stream.print("{} ", tree.tokenSlice(noalias_token)); - } - if (param_decl.name_token) |name_token| { - try stream.print("{}: ", tree.tokenSlice(name_token)); - } - if (param_decl.var_args_token) |var_args_token| { - try stream.print("{}", tree.tokenSlice(var_args_token)); - } else { - try stack.append(RenderState { .Expression = param_decl.type_node}); - } - }, - RenderState.Text => |bytes| { - try stream.write(bytes); - }, - RenderState.Expression => |base| switch (base.id) { - ast.Node.Id.Identifier => { - const identifier = @fieldParentPtr(ast.Node.Identifier, "base", base); - try stream.print("{}", tree.tokenSlice(identifier.token)); + if (async_attr.allocator_type) |allocator_type| { + try stream.write("<"); + try renderExpression(allocator, stream, tree, indent, allocator_type); + try stream.write(">"); + } + }, + ast.Node.Id.Suspend => { + const suspend_node = @fieldParentPtr(ast.Node.Suspend, "base", base); + if (suspend_node.label) |label| { + try stream.print("{}: ", tree.tokenSlice(label)); + } + try stream.print("{}", tree.tokenSlice(suspend_node.suspend_token)); + + if (suspend_node.payload) |payload| { + try stream.write(" "); + try renderExpression(allocator, stream, tree, indent, payload); + } + + if (suspend_node.body) |body| { + try stream.write(" "); + try renderExpression(allocator, stream, tree, indent, body); + } + + }, + + ast.Node.Id.InfixOp => { + const infix_op_node = @fieldParentPtr(ast.Node.InfixOp, "base", base); + + try renderExpression(allocator, stream, tree, indent, infix_op_node.lhs); + + const text = switch (infix_op_node.op) { + ast.Node.InfixOp.Op.Add => " + ", + ast.Node.InfixOp.Op.AddWrap => " +% ", + ast.Node.InfixOp.Op.ArrayCat => " ++ ", + ast.Node.InfixOp.Op.ArrayMult => " ** ", + ast.Node.InfixOp.Op.Assign => " = ", + ast.Node.InfixOp.Op.AssignBitAnd => " &= ", + ast.Node.InfixOp.Op.AssignBitOr => " |= ", + ast.Node.InfixOp.Op.AssignBitShiftLeft => " <<= ", + ast.Node.InfixOp.Op.AssignBitShiftRight => " >>= ", + ast.Node.InfixOp.Op.AssignBitXor => " ^= ", + ast.Node.InfixOp.Op.AssignDiv => " /= ", + ast.Node.InfixOp.Op.AssignMinus => " -= ", + ast.Node.InfixOp.Op.AssignMinusWrap => " -%= ", + ast.Node.InfixOp.Op.AssignMod => " %= ", + ast.Node.InfixOp.Op.AssignPlus => " += ", + ast.Node.InfixOp.Op.AssignPlusWrap => " +%= ", + ast.Node.InfixOp.Op.AssignTimes => " *= ", + ast.Node.InfixOp.Op.AssignTimesWarp => " *%= ", + ast.Node.InfixOp.Op.BangEqual => " != ", + ast.Node.InfixOp.Op.BitAnd => " & ", + ast.Node.InfixOp.Op.BitOr => " | ", + ast.Node.InfixOp.Op.BitShiftLeft => " << ", + ast.Node.InfixOp.Op.BitShiftRight => " >> ", + ast.Node.InfixOp.Op.BitXor => " ^ ", + ast.Node.InfixOp.Op.BoolAnd => " and ", + ast.Node.InfixOp.Op.BoolOr => " or ", + ast.Node.InfixOp.Op.Div => " / ", + ast.Node.InfixOp.Op.EqualEqual => " == ", + ast.Node.InfixOp.Op.ErrorUnion => "!", + ast.Node.InfixOp.Op.GreaterOrEqual => " >= ", + ast.Node.InfixOp.Op.GreaterThan => " > ", + ast.Node.InfixOp.Op.LessOrEqual => " <= ", + ast.Node.InfixOp.Op.LessThan => " < ", + ast.Node.InfixOp.Op.MergeErrorSets => " || ", + ast.Node.InfixOp.Op.Mod => " % ", + ast.Node.InfixOp.Op.Mult => " * ", + ast.Node.InfixOp.Op.MultWrap => " *% ", + ast.Node.InfixOp.Op.Period => ".", + ast.Node.InfixOp.Op.Sub => " - ", + ast.Node.InfixOp.Op.SubWrap => " -% ", + ast.Node.InfixOp.Op.UnwrapMaybe => " ?? ", + ast.Node.InfixOp.Op.Range => " ... ", + ast.Node.InfixOp.Op.Catch => |maybe_payload| blk: { + try stream.write(" catch "); + if (maybe_payload) |payload| { + try renderExpression(allocator, stream, tree, indent, payload); + try stream.write(" "); + } + break :blk ""; }, - ast.Node.Id.Block => { - const block = @fieldParentPtr(ast.Node.Block, "base", base); - if (block.label) |label| { - try stream.print("{}: ", tree.tokenSlice(label)); + }; + + try stream.write(text); + try renderExpression(allocator, stream, tree, indent, infix_op_node.rhs); + }, + + ast.Node.Id.PrefixOp => { + const prefix_op_node = @fieldParentPtr(ast.Node.PrefixOp, "base", base); + + switch (prefix_op_node.op) { + ast.Node.PrefixOp.Op.AddrOf => |addr_of_info| { + try stream.write("&"); + if (addr_of_info.align_expr) |align_expr| { + try stream.write("align("); + try renderExpression(allocator, stream, tree, indent, align_expr); + try stream.write(") "); } + if (addr_of_info.const_token != null) { + try stream.write("const "); + } + if (addr_of_info.volatile_token != null) { + try stream.write("volatile "); + } + }, + ast.Node.PrefixOp.Op.SliceType => |addr_of_info| { + try stream.write("[]"); + if (addr_of_info.align_expr) |align_expr| { + try stream.print("align("); + try renderExpression(allocator, stream, tree, indent, align_expr); + try stream.print(") "); + } + if (addr_of_info.const_token != null) { + try stream.print("const "); + } + if (addr_of_info.volatile_token != null) { + try stream.print("volatile "); + } + }, + ast.Node.PrefixOp.Op.ArrayType => |array_index| { + try stream.print("["); + try renderExpression(allocator, stream, tree, indent, array_index); + try stream.print("]"); + }, + ast.Node.PrefixOp.Op.BitNot => try stream.write("~"), + ast.Node.PrefixOp.Op.BoolNot => try stream.write("!"), + ast.Node.PrefixOp.Op.Deref => try stream.write("*"), + ast.Node.PrefixOp.Op.Negation => try stream.write("-"), + ast.Node.PrefixOp.Op.NegationWrap => try stream.write("-%"), + ast.Node.PrefixOp.Op.Try => try stream.write("try "), + ast.Node.PrefixOp.Op.UnwrapMaybe => try stream.write("??"), + ast.Node.PrefixOp.Op.MaybeType => try stream.write("?"), + ast.Node.PrefixOp.Op.Await => try stream.write("await "), + ast.Node.PrefixOp.Op.Cancel => try stream.write("cancel "), + ast.Node.PrefixOp.Op.Resume => try stream.write("resume "), + } + + try renderExpression(allocator, stream, tree, indent, prefix_op_node.rhs); + }, + + ast.Node.Id.SuffixOp => { + const suffix_op = @fieldParentPtr(ast.Node.SuffixOp, "base", base); + + switch (suffix_op.op) { + @TagType(ast.Node.SuffixOp.Op).Call => |*call_info| { + if (call_info.async_attr) |async_attr| { + try renderExpression(allocator, stream, tree, indent, &async_attr.base); + try stream.write(" "); + } + + try renderExpression(allocator, stream, tree, indent, suffix_op.lhs); + try stream.write("("); + + var it = call_info.params.iterator(0); + while (it.next()) |param_node| { + try renderExpression(allocator, stream, tree, indent, *param_node); + if (it.peek() != null) { + try stream.write(", "); + } + } + + try stream.write(")"); + }, + + ast.Node.SuffixOp.Op.ArrayAccess => |index_expr| { + try renderExpression(allocator, stream, tree, indent, suffix_op.lhs); + try stream.write("["); + try renderExpression(allocator, stream, tree, indent, index_expr); + try stream.write("]"); + }, - if (block.statements.len == 0) { + @TagType(ast.Node.SuffixOp.Op).Slice => |range| { + try renderExpression(allocator, stream, tree, indent, suffix_op.lhs); + try stream.write("["); + try renderExpression(allocator, stream, tree, indent, range.start); + try stream.write(".."); + if (range.end) |end| { + try renderExpression(allocator, stream, tree, indent, end); + } + try stream.write("]"); + }, + + ast.Node.SuffixOp.Op.StructInitializer => |*field_inits| { + if (field_inits.len == 0) { + try renderExpression(allocator, stream, tree, indent, suffix_op.lhs); + try stream.write("{}"); + return; + } + + if (field_inits.len == 1) { + const field_init = *field_inits.at(0); + + try renderExpression(allocator, stream, tree, indent, suffix_op.lhs); + try stream.write("{ "); + try renderExpression(allocator, stream, tree, indent, field_init); + try stream.write(" }"); + return; + } + + try renderExpression(allocator, stream, tree, indent, suffix_op.lhs); + try stream.write("{\n"); + + const new_indent = indent + indent_delta; + + var it = field_inits.iterator(0); + while (it.next()) |field_init| { + try stream.writeByteNTimes(' ', new_indent); + try renderExpression(allocator, stream, tree, new_indent, *field_init); + if ((*field_init).id != ast.Node.Id.LineComment) { + try stream.write(","); + } + if (it.peek()) |next_field_init| { + const n = if (nodeLineOffset(tree, *field_init, *next_field_init) >= 2) u8(2) else u8(1); + try stream.writeByteNTimes('\n', n); + } + } + + try stream.write("\n"); + try stream.writeByteNTimes(' ', indent); + try stream.write("}"); + }, + + ast.Node.SuffixOp.Op.ArrayInitializer => |*exprs| { + + if (exprs.len == 0) { + try renderExpression(allocator, stream, tree, indent, suffix_op.lhs); try stream.write("{}"); - } else { + return; + } + if (exprs.len == 1) { + const expr = *exprs.at(0); + + try renderExpression(allocator, stream, tree, indent, suffix_op.lhs); try stream.write("{"); - try stack.append(RenderState { .Text = "}"}); - try stack.append(RenderState.PrintIndent); - try stack.append(RenderState { .Indent = indent}); - try stack.append(RenderState { .Text = "\n"}); - var i = block.statements.len; - while (i != 0) { - i -= 1; - const statement_node = *block.statements.at(i); - try stack.append(RenderState { .Statement = statement_node}); - try stack.append(RenderState.PrintIndent); - try stack.append(RenderState { .Indent = indent + indent_delta}); - try stack.append(RenderState { - .Text = blk: { - if (i != 0) { - const prev_node = *block.statements.at(i - 1); - const prev_node_last_token_end = tree.tokens.at(prev_node.lastToken()).end; - const loc = tree.tokenLocation(prev_node_last_token_end, statement_node.firstToken()); - if (loc.line >= 2) { - break :blk "\n\n"; - } - } - break :blk "\n"; - }, - }); - } - } - }, - ast.Node.Id.Defer => { - const defer_node = @fieldParentPtr(ast.Node.Defer, "base", base); - try stream.print("{} ", tree.tokenSlice(defer_node.defer_token)); - try stack.append(RenderState { .Expression = defer_node.expr }); - }, - ast.Node.Id.Comptime => { - const comptime_node = @fieldParentPtr(ast.Node.Comptime, "base", base); - try stream.print("{} ", tree.tokenSlice(comptime_node.comptime_token)); - try stack.append(RenderState { .Expression = comptime_node.expr }); - }, - ast.Node.Id.AsyncAttribute => { - const async_attr = @fieldParentPtr(ast.Node.AsyncAttribute, "base", base); - try stream.print("{}", tree.tokenSlice(async_attr.async_token)); - - if (async_attr.allocator_type) |allocator_type| { - try stack.append(RenderState { .Text = ">" }); - try stack.append(RenderState { .Expression = allocator_type }); - try stack.append(RenderState { .Text = "<" }); + try renderExpression(allocator, stream, tree, indent, expr); + try stream.write("}"); + return; } - }, - ast.Node.Id.Suspend => { - const suspend_node = @fieldParentPtr(ast.Node.Suspend, "base", base); - if (suspend_node.label) |label| { - try stream.print("{}: ", tree.tokenSlice(label)); - } - try stream.print("{}", tree.tokenSlice(suspend_node.suspend_token)); - if (suspend_node.body) |body| { - try stack.append(RenderState { .Expression = body }); - try stack.append(RenderState { .Text = " " }); - } + try renderExpression(allocator, stream, tree, indent, suffix_op.lhs); - if (suspend_node.payload) |payload| { - try stack.append(RenderState { .Expression = payload }); - try stack.append(RenderState { .Text = " " }); - } - }, - ast.Node.Id.InfixOp => { - const prefix_op_node = @fieldParentPtr(ast.Node.InfixOp, "base", base); - try stack.append(RenderState { .Expression = prefix_op_node.rhs }); - - if (prefix_op_node.op == ast.Node.InfixOp.Op.Catch) { - if (prefix_op_node.op.Catch) |payload| { - try stack.append(RenderState { .Text = " " }); - try stack.append(RenderState { .Expression = payload }); + const new_indent = indent + indent_delta; + try stream.write("{\n"); + + var it = exprs.iterator(0); + while (it.next()) |expr| { + try stream.writeByteNTimes(' ', new_indent); + try renderExpression(allocator, stream, tree, new_indent, *expr); + try stream.write(","); + + if (it.peek()) |next_expr| { + const n = if (nodeLineOffset(tree, *expr, *next_expr) >= 2) u8(2) else u8(1); + try stream.writeByteNTimes('\n', n); } - try stack.append(RenderState { .Text = " catch " }); - } else { - const text = switch (prefix_op_node.op) { - ast.Node.InfixOp.Op.Add => " + ", - ast.Node.InfixOp.Op.AddWrap => " +% ", - ast.Node.InfixOp.Op.ArrayCat => " ++ ", - ast.Node.InfixOp.Op.ArrayMult => " ** ", - ast.Node.InfixOp.Op.Assign => " = ", - ast.Node.InfixOp.Op.AssignBitAnd => " &= ", - ast.Node.InfixOp.Op.AssignBitOr => " |= ", - ast.Node.InfixOp.Op.AssignBitShiftLeft => " <<= ", - ast.Node.InfixOp.Op.AssignBitShiftRight => " >>= ", - ast.Node.InfixOp.Op.AssignBitXor => " ^= ", - ast.Node.InfixOp.Op.AssignDiv => " /= ", - ast.Node.InfixOp.Op.AssignMinus => " -= ", - ast.Node.InfixOp.Op.AssignMinusWrap => " -%= ", - ast.Node.InfixOp.Op.AssignMod => " %= ", - ast.Node.InfixOp.Op.AssignPlus => " += ", - ast.Node.InfixOp.Op.AssignPlusWrap => " +%= ", - ast.Node.InfixOp.Op.AssignTimes => " *= ", - ast.Node.InfixOp.Op.AssignTimesWarp => " *%= ", - ast.Node.InfixOp.Op.BangEqual => " != ", - ast.Node.InfixOp.Op.BitAnd => " & ", - ast.Node.InfixOp.Op.BitOr => " | ", - ast.Node.InfixOp.Op.BitShiftLeft => " << ", - ast.Node.InfixOp.Op.BitShiftRight => " >> ", - ast.Node.InfixOp.Op.BitXor => " ^ ", - ast.Node.InfixOp.Op.BoolAnd => " and ", - ast.Node.InfixOp.Op.BoolOr => " or ", - ast.Node.InfixOp.Op.Div => " / ", - ast.Node.InfixOp.Op.EqualEqual => " == ", - ast.Node.InfixOp.Op.ErrorUnion => "!", - ast.Node.InfixOp.Op.GreaterOrEqual => " >= ", - ast.Node.InfixOp.Op.GreaterThan => " > ", - ast.Node.InfixOp.Op.LessOrEqual => " <= ", - ast.Node.InfixOp.Op.LessThan => " < ", - ast.Node.InfixOp.Op.MergeErrorSets => " || ", - ast.Node.InfixOp.Op.Mod => " % ", - ast.Node.InfixOp.Op.Mult => " * ", - ast.Node.InfixOp.Op.MultWrap => " *% ", - ast.Node.InfixOp.Op.Period => ".", - ast.Node.InfixOp.Op.Sub => " - ", - ast.Node.InfixOp.Op.SubWrap => " -% ", - ast.Node.InfixOp.Op.UnwrapMaybe => " ?? ", - ast.Node.InfixOp.Op.Range => " ... ", - ast.Node.InfixOp.Op.Catch => unreachable, - }; - - try stack.append(RenderState { .Text = text }); } - try stack.append(RenderState { .Expression = prefix_op_node.lhs }); - }, - ast.Node.Id.PrefixOp => { - const prefix_op_node = @fieldParentPtr(ast.Node.PrefixOp, "base", base); - try stack.append(RenderState { .Expression = prefix_op_node.rhs }); - switch (prefix_op_node.op) { - ast.Node.PrefixOp.Op.AddrOf => |addr_of_info| { - try stream.write("&"); - if (addr_of_info.volatile_token != null) { - try stack.append(RenderState { .Text = "volatile "}); - } - if (addr_of_info.const_token != null) { - try stack.append(RenderState { .Text = "const "}); - } - if (addr_of_info.align_expr) |align_expr| { - try stream.print("align("); - try stack.append(RenderState { .Text = ") "}); - try stack.append(RenderState { .Expression = align_expr}); - } - }, - ast.Node.PrefixOp.Op.SliceType => |addr_of_info| { - try stream.write("[]"); - if (addr_of_info.volatile_token != null) { - try stack.append(RenderState { .Text = "volatile "}); - } - if (addr_of_info.const_token != null) { - try stack.append(RenderState { .Text = "const "}); - } - if (addr_of_info.align_expr) |align_expr| { - try stream.print("align("); - try stack.append(RenderState { .Text = ") "}); - try stack.append(RenderState { .Expression = align_expr}); - } - }, - ast.Node.PrefixOp.Op.ArrayType => |array_index| { - try stack.append(RenderState { .Text = "]"}); - try stack.append(RenderState { .Expression = array_index}); - try stack.append(RenderState { .Text = "["}); - }, - ast.Node.PrefixOp.Op.BitNot => try stream.write("~"), - ast.Node.PrefixOp.Op.BoolNot => try stream.write("!"), - ast.Node.PrefixOp.Op.Deref => try stream.write("*"), - ast.Node.PrefixOp.Op.Negation => try stream.write("-"), - ast.Node.PrefixOp.Op.NegationWrap => try stream.write("-%"), - ast.Node.PrefixOp.Op.Try => try stream.write("try "), - ast.Node.PrefixOp.Op.UnwrapMaybe => try stream.write("??"), - ast.Node.PrefixOp.Op.MaybeType => try stream.write("?"), - ast.Node.PrefixOp.Op.Await => try stream.write("await "), - ast.Node.PrefixOp.Op.Cancel => try stream.write("cancel "), - ast.Node.PrefixOp.Op.Resume => try stream.write("resume "), + + try stream.write("\n"); + try stream.writeByteNTimes(' ', indent); + try stream.write("}"); + }, + } + }, + + ast.Node.Id.ControlFlowExpression => { + const flow_expr = @fieldParentPtr(ast.Node.ControlFlowExpression, "base", base); + + switch (flow_expr.kind) { + ast.Node.ControlFlowExpression.Kind.Break => |maybe_label| { + try stream.print("break"); + if (maybe_label) |label| { + try stream.print(" :"); + try renderExpression(allocator, stream, tree, indent, label); + } + }, + ast.Node.ControlFlowExpression.Kind.Continue => |maybe_label| { + try stream.print("continue"); + if (maybe_label) |label| { + try stream.print(" :"); + try renderExpression(allocator, stream, tree, indent, label); + } + }, + ast.Node.ControlFlowExpression.Kind.Return => { + try stream.print("return"); + }, + + } + + if (flow_expr.rhs) |rhs| { + try stream.write(" "); + try renderExpression(allocator, stream, tree, indent, rhs); + } + }, + + ast.Node.Id.Payload => { + const payload = @fieldParentPtr(ast.Node.Payload, "base", base); + + try stream.write("|"); + try renderExpression(allocator, stream, tree, indent, payload.error_symbol); + try stream.write("|"); + }, + + ast.Node.Id.PointerPayload => { + const payload = @fieldParentPtr(ast.Node.PointerPayload, "base", base); + + try stream.write("|"); + if (payload.ptr_token) |ptr_token| { + try stream.write(tree.tokenSlice(ptr_token)); + } + try renderExpression(allocator, stream, tree, indent, payload.value_symbol); + try stream.write("|"); + }, + + ast.Node.Id.PointerIndexPayload => { + const payload = @fieldParentPtr(ast.Node.PointerIndexPayload, "base", base); + + try stream.write("|"); + if (payload.ptr_token) |ptr_token| { + try stream.write(tree.tokenSlice(ptr_token)); + } + try renderExpression(allocator, stream, tree, indent, payload.value_symbol); + + if (payload.index_symbol) |index_symbol| { + try stream.write(", "); + try renderExpression(allocator, stream, tree, indent, index_symbol); + } + + try stream.write("|"); + }, + + ast.Node.Id.GroupedExpression => { + const grouped_expr = @fieldParentPtr(ast.Node.GroupedExpression, "base", base); + + try stream.write("("); + try renderExpression(allocator, stream, tree, indent, grouped_expr.expr); + try stream.write(")"); + }, + + ast.Node.Id.FieldInitializer => { + const field_init = @fieldParentPtr(ast.Node.FieldInitializer, "base", base); + + try stream.print(".{} = ", tree.tokenSlice(field_init.name_token)); + try renderExpression(allocator, stream, tree, indent, field_init.expr); + }, + + ast.Node.Id.IntegerLiteral => { + const integer_literal = @fieldParentPtr(ast.Node.IntegerLiteral, "base", base); + try stream.print("{}", tree.tokenSlice(integer_literal.token)); + }, + ast.Node.Id.FloatLiteral => { + const float_literal = @fieldParentPtr(ast.Node.FloatLiteral, "base", base); + try stream.print("{}", tree.tokenSlice(float_literal.token)); + }, + ast.Node.Id.StringLiteral => { + const string_literal = @fieldParentPtr(ast.Node.StringLiteral, "base", base); + try stream.print("{}", tree.tokenSlice(string_literal.token)); + }, + ast.Node.Id.CharLiteral => { + const char_literal = @fieldParentPtr(ast.Node.CharLiteral, "base", base); + try stream.print("{}", tree.tokenSlice(char_literal.token)); + }, + ast.Node.Id.BoolLiteral => { + const bool_literal = @fieldParentPtr(ast.Node.CharLiteral, "base", base); + try stream.print("{}", tree.tokenSlice(bool_literal.token)); + }, + ast.Node.Id.NullLiteral => { + const null_literal = @fieldParentPtr(ast.Node.NullLiteral, "base", base); + try stream.print("{}", tree.tokenSlice(null_literal.token)); + }, + ast.Node.Id.ThisLiteral => { + const this_literal = @fieldParentPtr(ast.Node.ThisLiteral, "base", base); + try stream.print("{}", tree.tokenSlice(this_literal.token)); + }, + ast.Node.Id.Unreachable => { + const unreachable_node = @fieldParentPtr(ast.Node.Unreachable, "base", base); + try stream.print("{}", tree.tokenSlice(unreachable_node.token)); + }, + ast.Node.Id.ErrorType => { + const error_type = @fieldParentPtr(ast.Node.ErrorType, "base", base); + try stream.print("{}", tree.tokenSlice(error_type.token)); + }, + ast.Node.Id.VarType => { + const var_type = @fieldParentPtr(ast.Node.VarType, "base", base); + try stream.print("{}", tree.tokenSlice(var_type.token)); + }, + ast.Node.Id.ContainerDecl => { + const container_decl = @fieldParentPtr(ast.Node.ContainerDecl, "base", base); + + switch (container_decl.layout) { + ast.Node.ContainerDecl.Layout.Packed => try stream.print("packed "), + ast.Node.ContainerDecl.Layout.Extern => try stream.print("extern "), + ast.Node.ContainerDecl.Layout.Auto => { }, + } + + switch (container_decl.kind) { + ast.Node.ContainerDecl.Kind.Struct => try stream.print("struct"), + ast.Node.ContainerDecl.Kind.Enum => try stream.print("enum"), + ast.Node.ContainerDecl.Kind.Union => try stream.print("union"), + } + + switch (container_decl.init_arg_expr) { + ast.Node.ContainerDecl.InitArg.None => try stream.write(" "), + ast.Node.ContainerDecl.InitArg.Enum => |enum_tag_type| { + if (enum_tag_type) |expr| { + try stream.write("(enum("); + try renderExpression(allocator, stream, tree, indent, expr); + try stream.write(")) "); + } else { + try stream.write("(enum) "); } }, - ast.Node.Id.SuffixOp => { - const suffix_op = @fieldParentPtr(ast.Node.SuffixOp, "base", base); - - switch (suffix_op.op) { - @TagType(ast.Node.SuffixOp.Op).Call => |*call_info| { - try stack.append(RenderState { .Text = ")"}); - var i = call_info.params.len; - while (i != 0) { - i -= 1; - const param_node = *call_info.params.at(i); - try stack.append(RenderState { .Expression = param_node}); - if (i != 0) { - try stack.append(RenderState { .Text = ", " }); - } - } - try stack.append(RenderState { .Text = "("}); - try stack.append(RenderState { .Expression = suffix_op.lhs }); - - if (call_info.async_attr) |async_attr| { - try stack.append(RenderState { .Text = " "}); - try stack.append(RenderState { .Expression = &async_attr.base }); - } - }, - ast.Node.SuffixOp.Op.ArrayAccess => |index_expr| { - try stack.append(RenderState { .Text = "]"}); - try stack.append(RenderState { .Expression = index_expr}); - try stack.append(RenderState { .Text = "["}); - try stack.append(RenderState { .Expression = suffix_op.lhs }); - }, - @TagType(ast.Node.SuffixOp.Op).Slice => |range| { - try stack.append(RenderState { .Text = "]"}); - if (range.end) |end| { - try stack.append(RenderState { .Expression = end}); - } - try stack.append(RenderState { .Text = ".."}); - try stack.append(RenderState { .Expression = range.start}); - try stack.append(RenderState { .Text = "["}); - try stack.append(RenderState { .Expression = suffix_op.lhs }); - }, - ast.Node.SuffixOp.Op.StructInitializer => |*field_inits| { - if (field_inits.len == 0) { - try stack.append(RenderState { .Text = "{}" }); - try stack.append(RenderState { .Expression = suffix_op.lhs }); - continue; - } - if (field_inits.len == 1) { - const field_init = *field_inits.at(0); - - try stack.append(RenderState { .Text = " }" }); - try stack.append(RenderState { .Expression = field_init }); - try stack.append(RenderState { .Text = "{ " }); - try stack.append(RenderState { .Expression = suffix_op.lhs }); - continue; - } - try stack.append(RenderState { .Text = "}"}); - try stack.append(RenderState.PrintIndent); - try stack.append(RenderState { .Indent = indent }); - try stack.append(RenderState { .Text = "\n" }); - var i = field_inits.len; - while (i != 0) { - i -= 1; - const field_init = *field_inits.at(i); - if (field_init.id != ast.Node.Id.LineComment) { - try stack.append(RenderState { .Text = "," }); - } - try stack.append(RenderState { .Expression = field_init }); - try stack.append(RenderState.PrintIndent); - if (i != 0) { - try stack.append(RenderState { .Text = blk: { - const prev_node = *field_inits.at(i - 1); - const prev_node_last_token_end = tree.tokens.at(prev_node.lastToken()).end; - const loc = tree.tokenLocation(prev_node_last_token_end, field_init.firstToken()); - if (loc.line >= 2) { - break :blk "\n\n"; - } - break :blk "\n"; - }}); - } - } - try stack.append(RenderState { .Indent = indent + indent_delta }); - try stack.append(RenderState { .Text = "{\n"}); - try stack.append(RenderState { .Expression = suffix_op.lhs }); - }, - ast.Node.SuffixOp.Op.ArrayInitializer => |*exprs| { - if (exprs.len == 0) { - try stack.append(RenderState { .Text = "{}" }); - try stack.append(RenderState { .Expression = suffix_op.lhs }); - continue; - } - if (exprs.len == 1) { - const expr = *exprs.at(0); - - try stack.append(RenderState { .Text = "}" }); - try stack.append(RenderState { .Expression = expr }); - try stack.append(RenderState { .Text = "{" }); - try stack.append(RenderState { .Expression = suffix_op.lhs }); - continue; - } - - try stack.append(RenderState { .Text = "}"}); - try stack.append(RenderState.PrintIndent); - try stack.append(RenderState { .Indent = indent }); - var i = exprs.len; - while (i != 0) { - i -= 1; - const expr = *exprs.at(i); - try stack.append(RenderState { .Text = ",\n" }); - try stack.append(RenderState { .Expression = expr }); - try stack.append(RenderState.PrintIndent); - } - try stack.append(RenderState { .Indent = indent + indent_delta }); - try stack.append(RenderState { .Text = "{\n"}); - try stack.append(RenderState { .Expression = suffix_op.lhs }); - }, - } + ast.Node.ContainerDecl.InitArg.Type => |type_expr| { + try stream.write("("); + try renderExpression(allocator, stream, tree, indent, type_expr); + try stream.write(") "); }, - ast.Node.Id.ControlFlowExpression => { - const flow_expr = @fieldParentPtr(ast.Node.ControlFlowExpression, "base", base); + } - if (flow_expr.rhs) |rhs| { - try stack.append(RenderState { .Expression = rhs }); - try stack.append(RenderState { .Text = " " }); - } + if (container_decl.fields_and_decls.len == 0) { + try stream.write("{}"); + } else { + try stream.write("{\n"); + const new_indent = indent + indent_delta; - switch (flow_expr.kind) { - ast.Node.ControlFlowExpression.Kind.Break => |maybe_label| { - try stream.print("break"); - if (maybe_label) |label| { - try stream.print(" :"); - try stack.append(RenderState { .Expression = label }); - } - }, - ast.Node.ControlFlowExpression.Kind.Continue => |maybe_label| { - try stream.print("continue"); - if (maybe_label) |label| { - try stream.print(" :"); - try stack.append(RenderState { .Expression = label }); - } - }, - ast.Node.ControlFlowExpression.Kind.Return => { - try stream.print("return"); - }, + var it = container_decl.fields_and_decls.iterator(0); + while (it.next()) |decl| { + try stream.writeByteNTimes(' ', new_indent); + try renderTopLevelDecl(allocator, stream, tree, new_indent, *decl); + if (it.peek()) |next_decl| { + const n = if (nodeLineOffset(tree, *decl, *next_decl) >= 2) u8(2) else u8(1); + try stream.writeByteNTimes('\n', n); } - }, - ast.Node.Id.Payload => { - const payload = @fieldParentPtr(ast.Node.Payload, "base", base); - try stack.append(RenderState { .Text = "|"}); - try stack.append(RenderState { .Expression = payload.error_symbol }); - try stack.append(RenderState { .Text = "|"}); - }, - ast.Node.Id.PointerPayload => { - const payload = @fieldParentPtr(ast.Node.PointerPayload, "base", base); - try stack.append(RenderState { .Text = "|"}); - try stack.append(RenderState { .Expression = payload.value_symbol }); + } - if (payload.ptr_token) |ptr_token| { - try stack.append(RenderState { .Text = tree.tokenSlice(ptr_token) }); - } + try stream.write("\n"); + try stream.writeByteNTimes(' ', indent); + try stream.write("}"); + } + }, + + ast.Node.Id.ErrorSetDecl => { + const err_set_decl = @fieldParentPtr(ast.Node.ErrorSetDecl, "base", base); + + if (err_set_decl.decls.len == 0) { + try stream.write("error{}"); + return; + } + + if (err_set_decl.decls.len == 1) blk: { + const node = *err_set_decl.decls.at(0); + + // if there are any doc comments or same line comments + // don't try to put it all on one line + if (node.cast(ast.Node.ErrorTag)) |tag| { + if (tag.doc_comments != null) break :blk; + } else { + break :blk; + } - try stack.append(RenderState { .Text = "|"}); - }, - ast.Node.Id.PointerIndexPayload => { - const payload = @fieldParentPtr(ast.Node.PointerIndexPayload, "base", base); - try stack.append(RenderState { .Text = "|"}); - if (payload.index_symbol) |index_symbol| { - try stack.append(RenderState { .Expression = index_symbol }); - try stack.append(RenderState { .Text = ", "}); - } + try stream.write("error{"); + try renderTopLevelDecl(allocator, stream, tree, indent, node); + try stream.write("}"); + return; + } - try stack.append(RenderState { .Expression = payload.value_symbol }); + try stream.write("error{\n"); + const new_indent = indent + indent_delta; - if (payload.ptr_token) |ptr_token| { - try stack.append(RenderState { .Text = tree.tokenSlice(ptr_token) }); - } + var it = err_set_decl.decls.iterator(0); + while (it.next()) |node| { + try stream.writeByteNTimes(' ', new_indent); + try renderTopLevelDecl(allocator, stream, tree, new_indent, *node); + if ((*node).id != ast.Node.Id.LineComment) { + try stream.write(","); + } + if (it.peek()) |next_node| { + const n = if (nodeLineOffset(tree, *node, *next_node) >= 2) u8(2) else u8(1); + try stream.writeByteNTimes('\n', n); + } + } + + try stream.write("\n"); + try stream.writeByteNTimes(' ', indent); + try stream.write("}"); + }, + + ast.Node.Id.MultilineStringLiteral => { + const multiline_str_literal = @fieldParentPtr(ast.Node.MultilineStringLiteral, "base", base); + try stream.print("\n"); + + var i : usize = 0; + while (i < multiline_str_literal.lines.len) : (i += 1) { + const t = *multiline_str_literal.lines.at(i); + try stream.writeByteNTimes(' ', indent + indent_delta); + try stream.print("{}", tree.tokenSlice(t)); + } + try stream.writeByteNTimes(' ', indent); + }, + ast.Node.Id.UndefinedLiteral => { + const undefined_literal = @fieldParentPtr(ast.Node.UndefinedLiteral, "base", base); + try stream.print("{}", tree.tokenSlice(undefined_literal.token)); + }, + + ast.Node.Id.BuiltinCall => { + const builtin_call = @fieldParentPtr(ast.Node.BuiltinCall, "base", base); + try stream.print("{}(", tree.tokenSlice(builtin_call.builtin_token)); + + var it = builtin_call.params.iterator(0); + while (it.next()) |param_node| { + try renderExpression(allocator, stream, tree, indent, *param_node); + if (it.peek() != null) { + try stream.write(", "); + } + } + try stream.write(")"); + }, - try stack.append(RenderState { .Text = "|"}); - }, - ast.Node.Id.GroupedExpression => { - const grouped_expr = @fieldParentPtr(ast.Node.GroupedExpression, "base", base); - try stack.append(RenderState { .Text = ")"}); - try stack.append(RenderState { .Expression = grouped_expr.expr }); - try stack.append(RenderState { .Text = "("}); - }, - ast.Node.Id.FieldInitializer => { - const field_init = @fieldParentPtr(ast.Node.FieldInitializer, "base", base); - try stream.print(".{} = ", tree.tokenSlice(field_init.name_token)); - try stack.append(RenderState { .Expression = field_init.expr }); - }, - ast.Node.Id.IntegerLiteral => { - const integer_literal = @fieldParentPtr(ast.Node.IntegerLiteral, "base", base); - try stream.print("{}", tree.tokenSlice(integer_literal.token)); - }, - ast.Node.Id.FloatLiteral => { - const float_literal = @fieldParentPtr(ast.Node.FloatLiteral, "base", base); - try stream.print("{}", tree.tokenSlice(float_literal.token)); - }, - ast.Node.Id.StringLiteral => { - const string_literal = @fieldParentPtr(ast.Node.StringLiteral, "base", base); - try stream.print("{}", tree.tokenSlice(string_literal.token)); - }, - ast.Node.Id.CharLiteral => { - const char_literal = @fieldParentPtr(ast.Node.CharLiteral, "base", base); - try stream.print("{}", tree.tokenSlice(char_literal.token)); - }, - ast.Node.Id.BoolLiteral => { - const bool_literal = @fieldParentPtr(ast.Node.CharLiteral, "base", base); - try stream.print("{}", tree.tokenSlice(bool_literal.token)); - }, - ast.Node.Id.NullLiteral => { - const null_literal = @fieldParentPtr(ast.Node.NullLiteral, "base", base); - try stream.print("{}", tree.tokenSlice(null_literal.token)); - }, - ast.Node.Id.ThisLiteral => { - const this_literal = @fieldParentPtr(ast.Node.ThisLiteral, "base", base); - try stream.print("{}", tree.tokenSlice(this_literal.token)); - }, - ast.Node.Id.Unreachable => { - const unreachable_node = @fieldParentPtr(ast.Node.Unreachable, "base", base); - try stream.print("{}", tree.tokenSlice(unreachable_node.token)); - }, - ast.Node.Id.ErrorType => { - const error_type = @fieldParentPtr(ast.Node.ErrorType, "base", base); - try stream.print("{}", tree.tokenSlice(error_type.token)); - }, - ast.Node.Id.VarType => { - const var_type = @fieldParentPtr(ast.Node.VarType, "base", base); - try stream.print("{}", tree.tokenSlice(var_type.token)); - }, - ast.Node.Id.ContainerDecl => { - const container_decl = @fieldParentPtr(ast.Node.ContainerDecl, "base", base); + ast.Node.Id.FnProto => { + const fn_proto = @fieldParentPtr(ast.Node.FnProto, "base", base); - switch (container_decl.layout) { - ast.Node.ContainerDecl.Layout.Packed => try stream.print("packed "), - ast.Node.ContainerDecl.Layout.Extern => try stream.print("extern "), - ast.Node.ContainerDecl.Layout.Auto => { }, - } + if (fn_proto.visib_token) |visib_token_index| { + const visib_token = tree.tokens.at(visib_token_index); + assert(visib_token.id == Token.Id.Keyword_pub or visib_token.id == Token.Id.Keyword_export); + try stream.print("{} ", tree.tokenSlice(visib_token_index)); + } - switch (container_decl.kind) { - ast.Node.ContainerDecl.Kind.Struct => try stream.print("struct"), - ast.Node.ContainerDecl.Kind.Enum => try stream.print("enum"), - ast.Node.ContainerDecl.Kind.Union => try stream.print("union"), - } + if (fn_proto.extern_export_inline_token) |extern_export_inline_token| { + try stream.print("{} ", tree.tokenSlice(extern_export_inline_token)); + } - if (container_decl.fields_and_decls.len == 0) { - try stack.append(RenderState { .Text = "{}"}); - } else { - try stack.append(RenderState { .Text = "}"}); - try stack.append(RenderState.PrintIndent); - try stack.append(RenderState { .Indent = indent }); - try stack.append(RenderState { .Text = "\n"}); - - var i = container_decl.fields_and_decls.len; - while (i != 0) { - i -= 1; - const node = *container_decl.fields_and_decls.at(i); - try stack.append(RenderState { .TopLevelDecl = node}); - try stack.append(RenderState.PrintIndent); - try stack.append(RenderState { - .Text = blk: { - if (i != 0) { - const prev_node = *container_decl.fields_and_decls.at(i - 1); - const prev_node_last_token_end = tree.tokens.at(prev_node.lastToken()).end; - const loc = tree.tokenLocation(prev_node_last_token_end, node.firstToken()); - if (loc.line >= 2) { - break :blk "\n\n"; - } - } - break :blk "\n"; - }, - }); - } - try stack.append(RenderState { .Indent = indent + indent_delta}); - try stack.append(RenderState { .Text = "{"}); - } + if (fn_proto.lib_name) |lib_name| { + try renderExpression(allocator, stream, tree, indent, lib_name); + try stream.write(" "); + } - switch (container_decl.init_arg_expr) { - ast.Node.ContainerDecl.InitArg.None => try stack.append(RenderState { .Text = " "}), - ast.Node.ContainerDecl.InitArg.Enum => |enum_tag_type| { - if (enum_tag_type) |expr| { - try stack.append(RenderState { .Text = ")) "}); - try stack.append(RenderState { .Expression = expr}); - try stack.append(RenderState { .Text = "(enum("}); - } else { - try stack.append(RenderState { .Text = "(enum) "}); - } - }, - ast.Node.ContainerDecl.InitArg.Type => |type_expr| { - try stack.append(RenderState { .Text = ") "}); - try stack.append(RenderState { .Expression = type_expr}); - try stack.append(RenderState { .Text = "("}); - }, - } - }, - ast.Node.Id.ErrorSetDecl => { - const err_set_decl = @fieldParentPtr(ast.Node.ErrorSetDecl, "base", base); + if (fn_proto.cc_token) |cc_token| { + try stream.print("{} ", tree.tokenSlice(cc_token)); + } - if (err_set_decl.decls.len == 0) { - try stream.write("error{}"); - continue; - } + if (fn_proto.async_attr) |async_attr| { + try renderExpression(allocator, stream, tree, indent, &async_attr.base); + try stream.write(" "); + } - if (err_set_decl.decls.len == 1) blk: { - const node = *err_set_decl.decls.at(0); + try stream.write("fn"); - // if there are any doc comments or same line comments - // don't try to put it all on one line - if (node.cast(ast.Node.ErrorTag)) |tag| { - if (tag.doc_comments != null) break :blk; - } else { - break :blk; - } + if (fn_proto.name_token) |name_token| { + try stream.print(" {}", tree.tokenSlice(name_token)); + } + try stream.write("("); - try stream.write("error{"); - try stack.append(RenderState { .Text = "}" }); - try stack.append(RenderState { .TopLevelDecl = node }); - continue; - } + var it = fn_proto.params.iterator(0); + while (it.next()) |param_decl_node| { + try renderParamDecl(allocator, stream, tree, indent, *param_decl_node); - try stream.write("error{"); + if (it.peek() != null) { + try stream.write(", "); + } + } - try stack.append(RenderState { .Text = "}"}); - try stack.append(RenderState.PrintIndent); - try stack.append(RenderState { .Indent = indent }); - try stack.append(RenderState { .Text = "\n"}); + try stream.write(") "); - var i = err_set_decl.decls.len; - while (i != 0) { - i -= 1; - const node = *err_set_decl.decls.at(i); - if (node.id != ast.Node.Id.LineComment) { - try stack.append(RenderState { .Text = "," }); - } - try stack.append(RenderState { .TopLevelDecl = node }); - try stack.append(RenderState.PrintIndent); - try stack.append(RenderState { - .Text = blk: { - if (i != 0) { - const prev_node = *err_set_decl.decls.at(i - 1); - const prev_node_last_token_end = tree.tokens.at(prev_node.lastToken()).end; - const loc = tree.tokenLocation(prev_node_last_token_end, node.firstToken()); - if (loc.line >= 2) { - break :blk "\n\n"; - } - } - break :blk "\n"; - }, - }); - } - try stack.append(RenderState { .Indent = indent + indent_delta}); - }, - ast.Node.Id.MultilineStringLiteral => { - const multiline_str_literal = @fieldParentPtr(ast.Node.MultilineStringLiteral, "base", base); - try stream.print("\n"); - - var i : usize = 0; - while (i < multiline_str_literal.lines.len) : (i += 1) { - const t = *multiline_str_literal.lines.at(i); - try stream.writeByteNTimes(' ', indent + indent_delta); - try stream.print("{}", tree.tokenSlice(t)); - } - try stream.writeByteNTimes(' ', indent); - }, - ast.Node.Id.UndefinedLiteral => { - const undefined_literal = @fieldParentPtr(ast.Node.UndefinedLiteral, "base", base); - try stream.print("{}", tree.tokenSlice(undefined_literal.token)); + if (fn_proto.align_expr) |align_expr| { + try stream.write("align("); + try renderExpression(allocator, stream, tree, indent, align_expr); + try stream.write(") "); + } + + switch (fn_proto.return_type) { + ast.Node.FnProto.ReturnType.Explicit => |node| { + try renderExpression(allocator, stream, tree, indent, node); }, - ast.Node.Id.BuiltinCall => { - const builtin_call = @fieldParentPtr(ast.Node.BuiltinCall, "base", base); - try stream.print("{}(", tree.tokenSlice(builtin_call.builtin_token)); - try stack.append(RenderState { .Text = ")"}); - var i = builtin_call.params.len; - while (i != 0) { - i -= 1; - const param_node = *builtin_call.params.at(i); - try stack.append(RenderState { .Expression = param_node}); - if (i != 0) { - try stack.append(RenderState { .Text = ", " }); - } - } + ast.Node.FnProto.ReturnType.InferErrorSet => |node| { + try stream.write("!"); + try renderExpression(allocator, stream, tree, indent, node); }, - ast.Node.Id.FnProto => { - const fn_proto = @fieldParentPtr(ast.Node.FnProto, "base", base); - - switch (fn_proto.return_type) { - ast.Node.FnProto.ReturnType.Explicit => |node| { - try stack.append(RenderState { .Expression = node}); - }, - ast.Node.FnProto.ReturnType.InferErrorSet => |node| { - try stack.append(RenderState { .Expression = node}); - try stack.append(RenderState { .Text = "!"}); - }, - } + } - if (fn_proto.align_expr) |align_expr| { - try stack.append(RenderState { .Text = ") " }); - try stack.append(RenderState { .Expression = align_expr}); - try stack.append(RenderState { .Text = "align(" }); - } + }, - try stack.append(RenderState { .Text = ") " }); - var i = fn_proto.params.len; - while (i != 0) { - i -= 1; - const param_decl_node = *fn_proto.params.at(i); - try stack.append(RenderState { .ParamDecl = param_decl_node}); - if (i != 0) { - try stack.append(RenderState { .Text = ", " }); - } - } + ast.Node.Id.PromiseType => { + const promise_type = @fieldParentPtr(ast.Node.PromiseType, "base", base); + try stream.write(tree.tokenSlice(promise_type.promise_token)); + if (promise_type.result) |result| { + try stream.write(tree.tokenSlice(result.arrow_token)); + try renderExpression(allocator, stream, tree, indent, result.return_type); + } + }, - try stack.append(RenderState { .Text = "(" }); - if (fn_proto.name_token) |name_token| { - try stack.append(RenderState { .Text = tree.tokenSlice(name_token) }); - try stack.append(RenderState { .Text = " " }); - } + ast.Node.Id.LineComment => { + const line_comment_node = @fieldParentPtr(ast.Node.LineComment, "base", base); + try stream.write(tree.tokenSlice(line_comment_node.token)); + }, - try stack.append(RenderState { .Text = "fn" }); + ast.Node.Id.DocComment => unreachable, // doc comments are attached to nodes - if (fn_proto.async_attr) |async_attr| { - try stack.append(RenderState { .Text = " " }); - try stack.append(RenderState { .Expression = &async_attr.base }); - } + ast.Node.Id.Switch => { + const switch_node = @fieldParentPtr(ast.Node.Switch, "base", base); - if (fn_proto.cc_token) |cc_token| { - try stack.append(RenderState { .Text = " " }); - try stack.append(RenderState { .Text = tree.tokenSlice(cc_token) }); - } + try stream.print("{} (", tree.tokenSlice(switch_node.switch_token)); + if (switch_node.cases.len == 0) { + try renderExpression(allocator, stream, tree, indent, switch_node.expr); + try stream.write(") {}"); + return; + } - if (fn_proto.lib_name) |lib_name| { - try stack.append(RenderState { .Text = " " }); - try stack.append(RenderState { .Expression = lib_name }); - } - if (fn_proto.extern_export_inline_token) |extern_export_inline_token| { - try stack.append(RenderState { .Text = " " }); - try stack.append(RenderState { .Text = tree.tokenSlice(extern_export_inline_token) }); - } + try renderExpression(allocator, stream, tree, indent, switch_node.expr); + try stream.write(") {\n"); - if (fn_proto.visib_token) |visib_token_index| { - const visib_token = tree.tokens.at(visib_token_index); - assert(visib_token.id == Token.Id.Keyword_pub or visib_token.id == Token.Id.Keyword_export); - try stack.append(RenderState { .Text = " " }); - try stack.append(RenderState { .Text = tree.tokenSlice(visib_token_index) }); - } - }, - ast.Node.Id.PromiseType => { - const promise_type = @fieldParentPtr(ast.Node.PromiseType, "base", base); - try stream.write(tree.tokenSlice(promise_type.promise_token)); - if (promise_type.result) |result| { - try stream.write(tree.tokenSlice(result.arrow_token)); - try stack.append(RenderState { .Expression = result.return_type}); - } - }, - ast.Node.Id.LineComment => { - const line_comment_node = @fieldParentPtr(ast.Node.LineComment, "base", base); - try stream.write(tree.tokenSlice(line_comment_node.token)); - }, - ast.Node.Id.DocComment => unreachable, // doc comments are attached to nodes - ast.Node.Id.Switch => { - const switch_node = @fieldParentPtr(ast.Node.Switch, "base", base); + const new_indent = indent + indent_delta; - try stream.print("{} (", tree.tokenSlice(switch_node.switch_token)); + var it = switch_node.cases.iterator(0); + while (it.next()) |node| { + try stream.writeByteNTimes(' ', new_indent); + try renderExpression(allocator, stream, tree, new_indent, *node); - if (switch_node.cases.len == 0) { - try stack.append(RenderState { .Text = ") {}"}); - try stack.append(RenderState { .Expression = switch_node.expr }); - continue; - } - - try stack.append(RenderState { .Text = "}"}); - try stack.append(RenderState.PrintIndent); - try stack.append(RenderState { .Indent = indent }); - try stack.append(RenderState { .Text = "\n"}); - - var i = switch_node.cases.len; - while (i != 0) { - i -= 1; - const node = *switch_node.cases.at(i); - try stack.append(RenderState { .Expression = node}); - try stack.append(RenderState.PrintIndent); - try stack.append(RenderState { - .Text = blk: { - if (i != 0) { - const prev_node = *switch_node.cases.at(i - 1); - const prev_node_last_token_end = tree.tokens.at(prev_node.lastToken()).end; - const loc = tree.tokenLocation(prev_node_last_token_end, node.firstToken()); - if (loc.line >= 2) { - break :blk "\n\n"; - } - } - break :blk "\n"; - }, - }); - } - try stack.append(RenderState { .Indent = indent + indent_delta}); - try stack.append(RenderState { .Text = ") {"}); - try stack.append(RenderState { .Expression = switch_node.expr }); - }, - ast.Node.Id.SwitchCase => { - const switch_case = @fieldParentPtr(ast.Node.SwitchCase, "base", base); - - try stack.append(RenderState { .Token = switch_case.lastToken() + 1 }); - try stack.append(RenderState { .Expression = switch_case.expr }); - if (switch_case.payload) |payload| { - try stack.append(RenderState { .Text = " " }); - try stack.append(RenderState { .Expression = payload }); - } - try stack.append(RenderState { .Text = " => "}); + if (it.peek()) |next_node| { + const n = if (nodeLineOffset(tree, *node, *next_node) >= 2) u8(2) else u8(1); + try stream.writeByteNTimes('\n', n); + } + } - var i = switch_case.items.len; - while (i != 0) { - i -= 1; - try stack.append(RenderState { .Expression = *switch_case.items.at(i) }); + try stream.write("\n"); + try stream.writeByteNTimes(' ', indent); + try stream.write("}"); + }, - if (i != 0) { - try stack.append(RenderState.PrintIndent); - try stack.append(RenderState { .Text = ",\n" }); - } - } - }, - ast.Node.Id.SwitchElse => { - const switch_else = @fieldParentPtr(ast.Node.SwitchElse, "base", base); - try stream.print("{}", tree.tokenSlice(switch_else.token)); - }, - ast.Node.Id.Else => { - const else_node = @fieldParentPtr(ast.Node.Else, "base", base); - try stream.print("{}", tree.tokenSlice(else_node.else_token)); - - switch (else_node.body.id) { - ast.Node.Id.Block, ast.Node.Id.If, - ast.Node.Id.For, ast.Node.Id.While, - ast.Node.Id.Switch => { - try stream.print(" "); - try stack.append(RenderState { .Expression = else_node.body }); - }, - else => { - try stack.append(RenderState { .Indent = indent }); - try stack.append(RenderState { .Expression = else_node.body }); - try stack.append(RenderState.PrintIndent); - try stack.append(RenderState { .Indent = indent + indent_delta }); - try stack.append(RenderState { .Text = "\n" }); - } - } + ast.Node.Id.SwitchCase => { + const switch_case = @fieldParentPtr(ast.Node.SwitchCase, "base", base); - if (else_node.payload) |payload| { - try stack.append(RenderState { .Text = " " }); - try stack.append(RenderState { .Expression = payload }); - } - }, - ast.Node.Id.While => { - const while_node = @fieldParentPtr(ast.Node.While, "base", base); - if (while_node.label) |label| { - try stream.print("{}: ", tree.tokenSlice(label)); - } + var it = switch_case.items.iterator(0); + while (it.next()) |node| { + try renderExpression(allocator, stream, tree, indent, *node); - if (while_node.inline_token) |inline_token| { - try stream.print("{} ", tree.tokenSlice(inline_token)); - } + if (it.peek() != null) { + try stream.write(",\n"); + try stream.writeByteNTimes(' ', indent); + } + } + + try stream.write(" => "); + + if (switch_case.payload) |payload| { + try renderExpression(allocator, stream, tree, indent, payload); + try stream.write(" "); + } + + try renderExpression(allocator, stream, tree, indent, switch_case.expr); + try renderToken(tree, stream, switch_case.lastToken() + 1, indent, true); + }, + ast.Node.Id.SwitchElse => { + const switch_else = @fieldParentPtr(ast.Node.SwitchElse, "base", base); + try stream.print("{}", tree.tokenSlice(switch_else.token)); + }, + ast.Node.Id.Else => { + const else_node = @fieldParentPtr(ast.Node.Else, "base", base); + try stream.print("{}", tree.tokenSlice(else_node.else_token)); + + const block_body = switch (else_node.body.id) { + ast.Node.Id.Block, ast.Node.Id.If, + ast.Node.Id.For, ast.Node.Id.While, + ast.Node.Id.Switch => true, + else => false, + }; + + if (block_body) { + try stream.write(" "); + } + + if (else_node.payload) |payload| { + try renderExpression(allocator, stream, tree, indent, payload); + try stream.write(" "); + } + + if (block_body) { + try renderExpression(allocator, stream, tree, indent, else_node.body); + } else { + try stream.write("\n"); + try stream.writeByteNTimes(' ', indent + indent_delta); + try renderExpression(allocator, stream, tree, indent, else_node.body); + } + }, + + ast.Node.Id.While => { + const while_node = @fieldParentPtr(ast.Node.While, "base", base); + + if (while_node.label) |label| { + try stream.print("{}: ", tree.tokenSlice(label)); + } + + if (while_node.inline_token) |inline_token| { + try stream.print("{} ", tree.tokenSlice(inline_token)); + } + + try stream.print("{} (", tree.tokenSlice(while_node.while_token)); + try renderExpression(allocator, stream, tree, indent, while_node.condition); + try stream.write(")"); + + if (while_node.payload) |payload| { + try stream.write(" "); + try renderExpression(allocator, stream, tree, indent, payload); + } + + if (while_node.continue_expr) |continue_expr| { + try stream.write(" : ("); + try renderExpression(allocator, stream, tree, indent, continue_expr); + try stream.write(")"); + } + + if (while_node.body.id == ast.Node.Id.Block) { + try stream.write(" "); + try renderExpression(allocator, stream, tree, indent, while_node.body); + } else { + try stream.write("\n"); + try stream.writeByteNTimes(' ', indent + indent_delta); + try renderExpression(allocator, stream, tree, indent, while_node.body); + } + + if (while_node.@"else") |@"else"| { + if (while_node.body.id == ast.Node.Id.Block) { + try stream.write(" "); + } else { + try stream.write("\n"); + try stream.writeByteNTimes(' ', indent); + } - try stream.print("{} ", tree.tokenSlice(while_node.while_token)); + try renderExpression(allocator, stream, tree, indent, &@"else".base); + } + }, + + ast.Node.Id.For => { + const for_node = @fieldParentPtr(ast.Node.For, "base", base); + if (for_node.label) |label| { + try stream.print("{}: ", tree.tokenSlice(label)); + } + + if (for_node.inline_token) |inline_token| { + try stream.print("{} ", tree.tokenSlice(inline_token)); + } + + try stream.print("{} (", tree.tokenSlice(for_node.for_token)); + try renderExpression(allocator, stream, tree, indent, for_node.array_expr); + try stream.write(")"); + + if (for_node.payload) |payload| { + try stream.write(" "); + try renderExpression(allocator, stream, tree, indent, payload); + } + + if (for_node.body.id == ast.Node.Id.Block) { + try stream.write(" "); + try renderExpression(allocator, stream, tree, indent, for_node.body); + } else { + try stream.write("\n"); + try stream.writeByteNTimes(' ', indent + indent_delta); + try renderExpression(allocator, stream, tree, indent, for_node.body); + } + + if (for_node.@"else") |@"else"| { + if (for_node.body.id == ast.Node.Id.Block) { + try stream.write(" "); + } else { + try stream.write("\n"); + try stream.writeByteNTimes(' ', indent); + } - if (while_node.@"else") |@"else"| { - try stack.append(RenderState { .Expression = &@"else".base }); + try renderExpression(allocator, stream, tree, indent, &@"else".base); + } + }, - if (while_node.body.id == ast.Node.Id.Block) { - try stack.append(RenderState { .Text = " " }); - } else { - try stack.append(RenderState.PrintIndent); - try stack.append(RenderState { .Text = "\n" }); - } - } + ast.Node.Id.If => { + const if_node = @fieldParentPtr(ast.Node.If, "base", base); + try stream.print("{} (", tree.tokenSlice(if_node.if_token)); - if (while_node.body.id == ast.Node.Id.Block) { - try stack.append(RenderState { .Expression = while_node.body }); - try stack.append(RenderState { .Text = " " }); - } else { - try stack.append(RenderState { .Indent = indent }); - try stack.append(RenderState { .Expression = while_node.body }); - try stack.append(RenderState.PrintIndent); - try stack.append(RenderState { .Indent = indent + indent_delta }); - try stack.append(RenderState { .Text = "\n" }); - } + try renderExpression(allocator, stream, tree, indent, if_node.condition); + try renderToken(tree, stream, if_node.condition.lastToken() + 1, indent, false); - if (while_node.continue_expr) |continue_expr| { - try stack.append(RenderState { .Text = ")" }); - try stack.append(RenderState { .Expression = continue_expr }); - try stack.append(RenderState { .Text = ": (" }); - try stack.append(RenderState { .Text = " " }); - } + if (if_node.payload) |payload| { + try renderExpression(allocator, stream, tree, indent, payload); + try stream.write(" "); + } - if (while_node.payload) |payload| { - try stack.append(RenderState { .Expression = payload }); - try stack.append(RenderState { .Text = " " }); - } + try renderExpression(allocator, stream, tree, indent, if_node.body); - try stack.append(RenderState { .Text = ")" }); - try stack.append(RenderState { .Expression = while_node.condition }); - try stack.append(RenderState { .Text = "(" }); - }, - ast.Node.Id.For => { - const for_node = @fieldParentPtr(ast.Node.For, "base", base); - if (for_node.label) |label| { - try stream.print("{}: ", tree.tokenSlice(label)); - } + switch (if_node.body.id) { + ast.Node.Id.Block, ast.Node.Id.If, ast.Node.Id.For, ast.Node.Id.While, ast.Node.Id.Switch => { + if (if_node.@"else") |@"else"| { + if (if_node.body.id == ast.Node.Id.Block) { + try stream.write(" "); + } else { + try stream.write("\n"); + try stream.writeByteNTimes(' ', indent); + } - if (for_node.inline_token) |inline_token| { - try stream.print("{} ", tree.tokenSlice(inline_token)); + try renderExpression(allocator, stream, tree, indent, &@"else".base); } + }, + else => { + if (if_node.@"else") |@"else"| { + try stream.print(" {} ", tree.tokenSlice(@"else".else_token)); - try stream.print("{} ", tree.tokenSlice(for_node.for_token)); - - if (for_node.@"else") |@"else"| { - try stack.append(RenderState { .Expression = &@"else".base }); - - if (for_node.body.id == ast.Node.Id.Block) { - try stack.append(RenderState { .Text = " " }); - } else { - try stack.append(RenderState.PrintIndent); - try stack.append(RenderState { .Text = "\n" }); + if (@"else".payload) |payload| { + try renderExpression(allocator, stream, tree, indent, payload); + try stream.write(" "); } - } - if (for_node.body.id == ast.Node.Id.Block) { - try stack.append(RenderState { .Expression = for_node.body }); - try stack.append(RenderState { .Text = " " }); - } else { - try stack.append(RenderState { .Indent = indent }); - try stack.append(RenderState { .Expression = for_node.body }); - try stack.append(RenderState.PrintIndent); - try stack.append(RenderState { .Indent = indent + indent_delta }); - try stack.append(RenderState { .Text = "\n" }); + try renderExpression(allocator, stream, tree, indent, @"else".body); } - - if (for_node.payload) |payload| { - try stack.append(RenderState { .Expression = payload }); - try stack.append(RenderState { .Text = " " }); + } + } + }, + + ast.Node.Id.Asm => { + const asm_node = @fieldParentPtr(ast.Node.Asm, "base", base); + try stream.print("{} ", tree.tokenSlice(asm_node.asm_token)); + + if (asm_node.volatile_token) |volatile_token| { + try stream.print("{} ", tree.tokenSlice(volatile_token)); + } + + try stream.print("("); + try renderExpression(allocator, stream, tree, indent, asm_node.template); + try stream.print("\n"); + const indent_once = indent + indent_delta; + try stream.writeByteNTimes(' ', indent_once); + try stream.print(": "); + const indent_extra = indent_once + 2; + + { + var it = asm_node.outputs.iterator(0); + while (it.next()) |asm_output| { + const node = &(*asm_output).base; + try renderExpression(allocator, stream, tree, indent_extra, node); + + if (it.peek()) |next_asm_output| { + const next_node = &(*next_asm_output).base; + const n = if (nodeLineOffset(tree, node, next_node) >= 2) u8(2) else u8(1); + try stream.writeByte(','); + try stream.writeByteNTimes('\n', n); + try stream.writeByteNTimes(' ', indent_extra); } + } + } - try stack.append(RenderState { .Text = ")" }); - try stack.append(RenderState { .Expression = for_node.array_expr }); - try stack.append(RenderState { .Text = "(" }); - }, - ast.Node.Id.If => { - const if_node = @fieldParentPtr(ast.Node.If, "base", base); - try stream.print("{} ", tree.tokenSlice(if_node.if_token)); - - switch (if_node.body.id) { - ast.Node.Id.Block, ast.Node.Id.If, - ast.Node.Id.For, ast.Node.Id.While, - ast.Node.Id.Switch => { - if (if_node.@"else") |@"else"| { - try stack.append(RenderState { .Expression = &@"else".base }); - - if (if_node.body.id == ast.Node.Id.Block) { - try stack.append(RenderState { .Text = " " }); - } else { - try stack.append(RenderState.PrintIndent); - try stack.append(RenderState { .Text = "\n" }); - } - } - }, - else => { - if (if_node.@"else") |@"else"| { - try stack.append(RenderState { .Expression = @"else".body }); - - if (@"else".payload) |payload| { - try stack.append(RenderState { .Text = " " }); - try stack.append(RenderState { .Expression = payload }); - } - - try stack.append(RenderState { .Text = " " }); - try stack.append(RenderState { .Text = tree.tokenSlice(@"else".else_token) }); - try stack.append(RenderState { .Text = " " }); - } - } - } + try stream.write("\n"); + try stream.writeByteNTimes(' ', indent_once); + try stream.write(": "); - try stack.append(RenderState { .Expression = if_node.body }); + { + var it = asm_node.inputs.iterator(0); + while (it.next()) |asm_input| { + const node = &(*asm_input).base; + try renderExpression(allocator, stream, tree, indent_extra, node); - if (if_node.payload) |payload| { - try stack.append(RenderState { .Text = " " }); - try stack.append(RenderState { .Expression = payload }); + if (it.peek()) |next_asm_input| { + const next_node = &(*next_asm_input).base; + const n = if (nodeLineOffset(tree, node, next_node) >= 2) u8(2) else u8(1); + try stream.writeByte(','); + try stream.writeByteNTimes('\n', n); + try stream.writeByteNTimes(' ', indent_extra); } + } + } - try stack.append(RenderState { .NonBreakToken = if_node.condition.lastToken() + 1 }); - try stack.append(RenderState { .Expression = if_node.condition }); - try stack.append(RenderState { .Text = "(" }); - }, - ast.Node.Id.Asm => { - const asm_node = @fieldParentPtr(ast.Node.Asm, "base", base); - try stream.print("{} ", tree.tokenSlice(asm_node.asm_token)); + try stream.write("\n"); + try stream.writeByteNTimes(' ', indent_once); + try stream.write(": "); - if (asm_node.volatile_token) |volatile_token| { - try stream.print("{} ", tree.tokenSlice(volatile_token)); - } + { + var it = asm_node.clobbers.iterator(0); + while (it.next()) |node| { + try renderExpression(allocator, stream, tree, indent_once, *node); - try stack.append(RenderState { .Indent = indent }); - try stack.append(RenderState { .Text = ")" }); - { - var i = asm_node.clobbers.len; - while (i != 0) { - i -= 1; - try stack.append(RenderState { .Expression = *asm_node.clobbers.at(i) }); - - if (i != 0) { - try stack.append(RenderState { .Text = ", " }); - } - } - } - try stack.append(RenderState { .Text = ": " }); - try stack.append(RenderState.PrintIndent); - try stack.append(RenderState { .Indent = indent + indent_delta }); - try stack.append(RenderState { .Text = "\n" }); - { - var i = asm_node.inputs.len; - while (i != 0) { - i -= 1; - const node = *asm_node.inputs.at(i); - try stack.append(RenderState { .Expression = &node.base}); - - if (i != 0) { - try stack.append(RenderState.PrintIndent); - try stack.append(RenderState { - .Text = blk: { - const prev_node = *asm_node.inputs.at(i - 1); - const prev_node_last_token_end = tree.tokens.at(prev_node.lastToken()).end; - const loc = tree.tokenLocation(prev_node_last_token_end, node.firstToken()); - if (loc.line >= 2) { - break :blk "\n\n"; - } - break :blk "\n"; - }, - }); - try stack.append(RenderState { .Text = "," }); - } - } + if (it.peek() != null) { + try stream.write(", "); } - try stack.append(RenderState { .Indent = indent + indent_delta + 2}); - try stack.append(RenderState { .Text = ": "}); - try stack.append(RenderState.PrintIndent); - try stack.append(RenderState { .Indent = indent + indent_delta}); - try stack.append(RenderState { .Text = "\n" }); - { - var i = asm_node.outputs.len; - while (i != 0) { - i -= 1; - const node = *asm_node.outputs.at(i); - try stack.append(RenderState { .Expression = &node.base}); - - if (i != 0) { - try stack.append(RenderState.PrintIndent); - try stack.append(RenderState { - .Text = blk: { - const prev_node = *asm_node.outputs.at(i - 1); - const prev_node_last_token_end = tree.tokens.at(prev_node.lastToken()).end; - const loc = tree.tokenLocation(prev_node_last_token_end, node.firstToken()); - if (loc.line >= 2) { - break :blk "\n\n"; - } - break :blk "\n"; - }, - }); - try stack.append(RenderState { .Text = "," }); - } - } - } - try stack.append(RenderState { .Indent = indent + indent_delta + 2}); - try stack.append(RenderState { .Text = ": "}); - try stack.append(RenderState.PrintIndent); - try stack.append(RenderState { .Indent = indent + indent_delta}); - try stack.append(RenderState { .Text = "\n" }); - try stack.append(RenderState { .Expression = asm_node.template }); - try stack.append(RenderState { .Text = "(" }); - }, - ast.Node.Id.AsmInput => { - const asm_input = @fieldParentPtr(ast.Node.AsmInput, "base", base); - - try stack.append(RenderState { .Text = ")"}); - try stack.append(RenderState { .Expression = asm_input.expr}); - try stack.append(RenderState { .Text = " ("}); - try stack.append(RenderState { .Expression = asm_input.constraint }); - try stack.append(RenderState { .Text = "] "}); - try stack.append(RenderState { .Expression = asm_input.symbolic_name }); - try stack.append(RenderState { .Text = "["}); - }, - ast.Node.Id.AsmOutput => { - const asm_output = @fieldParentPtr(ast.Node.AsmOutput, "base", base); - - try stack.append(RenderState { .Text = ")"}); - switch (asm_output.kind) { - ast.Node.AsmOutput.Kind.Variable => |variable_name| { - try stack.append(RenderState { .Expression = &variable_name.base}); - }, - ast.Node.AsmOutput.Kind.Return => |return_type| { - try stack.append(RenderState { .Expression = return_type}); - try stack.append(RenderState { .Text = "-> "}); - }, - } - try stack.append(RenderState { .Text = " ("}); - try stack.append(RenderState { .Expression = asm_output.constraint }); - try stack.append(RenderState { .Text = "] "}); - try stack.append(RenderState { .Expression = asm_output.symbolic_name }); - try stack.append(RenderState { .Text = "["}); - }, - - ast.Node.Id.StructField, - ast.Node.Id.UnionTag, - ast.Node.Id.EnumTag, - ast.Node.Id.ErrorTag, - ast.Node.Id.Root, - ast.Node.Id.VarDecl, - ast.Node.Id.Use, - ast.Node.Id.TestDecl, - ast.Node.Id.ParamDecl => unreachable, - }, - RenderState.Statement => |base| { - switch (base.id) { - ast.Node.Id.VarDecl => { - const var_decl = @fieldParentPtr(ast.Node.VarDecl, "base", base); - try stack.append(RenderState { .VarDecl = var_decl}); - }, - else => { - try stack.append(RenderState { .MaybeSemiColon = base }); - try stack.append(RenderState { .Expression = base }); - }, - } - }, - RenderState.Indent => |new_indent| indent = new_indent, - RenderState.PrintIndent => try stream.writeByteNTimes(' ', indent), - RenderState.Token => |token_index| try renderToken(tree, stream, token_index, indent, true), - RenderState.NonBreakToken => |token_index| try renderToken(tree, stream, token_index, indent, false), - RenderState.MaybeSemiColon => |base| { - if (base.requireSemiColon()) { - const semicolon_index = base.lastToken() + 1; - assert(tree.tokens.at(semicolon_index).id == Token.Id.Semicolon); - try renderToken(tree, stream, semicolon_index, indent, true); } - }, + } + + try stream.write(")"); + }, + + ast.Node.Id.AsmInput => { + const asm_input = @fieldParentPtr(ast.Node.AsmInput, "base", base); + + try stream.write("["); + try renderExpression(allocator, stream, tree, indent, asm_input.symbolic_name); + try stream.write("] "); + try renderExpression(allocator, stream, tree, indent, asm_input.constraint); + try stream.write(" ("); + try renderExpression(allocator, stream, tree, indent, asm_input.expr); + try stream.write(")"); + }, + + ast.Node.Id.AsmOutput => { + const asm_output = @fieldParentPtr(ast.Node.AsmOutput, "base", base); + + try stream.write("["); + try renderExpression(allocator, stream, tree, indent, asm_output.symbolic_name); + try stream.write("] "); + try renderExpression(allocator, stream, tree, indent, asm_output.constraint); + try stream.write(" ("); + + switch (asm_output.kind) { + ast.Node.AsmOutput.Kind.Variable => |variable_name| { + try renderExpression(allocator, stream, tree, indent, &variable_name.base); + }, + ast.Node.AsmOutput.Kind.Return => |return_type| { + try stream.write("-> "); + try renderExpression(allocator, stream, tree, indent, return_type); + }, + } + + try stream.write(")"); + }, + + ast.Node.Id.StructField, + ast.Node.Id.UnionTag, + ast.Node.Id.EnumTag, + ast.Node.Id.ErrorTag, + ast.Node.Id.Root, + ast.Node.Id.VarDecl, + ast.Node.Id.Use, + ast.Node.Id.TestDecl, + ast.Node.Id.ParamDecl => unreachable, + } +} + +fn renderVarDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent: usize, var_decl: &ast.Node.VarDecl) (@typeOf(stream).Child.Error || Error)!void { + if (var_decl.visib_token) |visib_token| { + try stream.print("{} ", tree.tokenSlice(visib_token)); + } + + if (var_decl.extern_export_token) |extern_export_token| { + try stream.print("{} ", tree.tokenSlice(extern_export_token)); + + if (var_decl.lib_name) |lib_name| { + try renderExpression(allocator, stream, tree, indent, lib_name); + try stream.write(" "); } } + + if (var_decl.comptime_token) |comptime_token| { + try stream.print("{} ", tree.tokenSlice(comptime_token)); + } + + try stream.print("{} {}", tree.tokenSlice(var_decl.mut_token), tree.tokenSlice(var_decl.name_token)); + + if (var_decl.type_node) |type_node| { + try stream.write(": "); + try renderExpression(allocator, stream, tree, indent, type_node); + } + + if (var_decl.align_node) |align_node| { + try stream.write(" align("); + try renderExpression(allocator, stream, tree, indent, align_node); + try stream.write(")"); + } + + if (var_decl.init_node) |init_node| { + const text = if (init_node.id == ast.Node.Id.MultilineStringLiteral) " =" else " = "; + try stream.write(text); + try renderExpression(allocator, stream, tree, indent, init_node); + } + + try renderToken(tree, stream, var_decl.semicolon_token, indent, true); +} + +fn maybeRenderSemicolon(stream: var, tree: &ast.Tree, indent: usize, base: &ast.Node) (@typeOf(stream).Child.Error || Error)!void { + if (base.requireSemiColon()) { + const semicolon_index = base.lastToken() + 1; + assert(tree.tokens.at(semicolon_index).id == Token.Id.Semicolon); + try renderToken(tree, stream, semicolon_index, indent, true); + } +} + +fn renderParamDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent: usize, base: &ast.Node) (@typeOf(stream).Child.Error || Error)!void { + const param_decl = @fieldParentPtr(ast.Node.ParamDecl, "base", base); + if (param_decl.comptime_token) |comptime_token| { + try stream.print("{} ", tree.tokenSlice(comptime_token)); + } + if (param_decl.noalias_token) |noalias_token| { + try stream.print("{} ", tree.tokenSlice(noalias_token)); + } + if (param_decl.name_token) |name_token| { + try stream.print("{}: ", tree.tokenSlice(name_token)); + } + if (param_decl.var_args_token) |var_args_token| { + try stream.print("{}", tree.tokenSlice(var_args_token)); + } else { + try renderExpression(allocator, stream, tree, indent, param_decl.type_node); + } +} + +fn renderStatement(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent: usize, base: &ast.Node) (@typeOf(stream).Child.Error || Error)!void { + switch (base.id) { + ast.Node.Id.VarDecl => { + const var_decl = @fieldParentPtr(ast.Node.VarDecl, "base", base); + try renderVarDecl(allocator, stream, tree, indent, var_decl); + }, + else => { + try renderExpression(allocator, stream, tree, indent, base); + try maybeRenderSemicolon(stream, tree, indent, base); + }, + } } -fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent: usize, line_break: bool) !void { +fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent: usize, line_break: bool) (@typeOf(stream).Child.Error || Error)!void { const token = tree.tokens.at(token_index); try stream.write(tree.tokenSlicePtr(token)); @@ -1255,7 +1212,7 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent } } -fn renderComments(tree: &ast.Tree, stream: var, node: var, indent: usize) !void { +fn renderComments(tree: &ast.Tree, stream: var, node: var, indent: usize) (@typeOf(stream).Child.Error || Error)!void { const comment = node.doc_comments ?? return; var it = comment.lines.iterator(0); while (it.next()) |line_token_index| { -- 2.54.0 From 548ddd1f0c35033cd7e0d1940975bc7185bf7346 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 12 May 2018 23:57:15 -0400 Subject: [PATCH 11/47] fix AST dumping code in self hosted compiler --- src/ir.cpp | 6 +++- std/zig/ast.zig | 82 +++++++++++++++++++++++++++++------------------ std/zig/parse.zig | 35 +------------------- 3 files changed, 57 insertions(+), 66 deletions(-) diff --git a/src/ir.cpp b/src/ir.cpp index 7bc837d9083eefbb923527fffab2d23b000b0ad0..31d22ca82a8ecc43c5333ba7b61d61e2d0e91297 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -18083,7 +18083,11 @@ static TypeTableEntry *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira if (type_is_invalid(end_value->value.type)) return ira->codegen->builtin_types.entry_invalid; - assert(start_value->value.type->id == TypeTableEntryIdEnum); + if (start_value->value.type->id != TypeTableEntryIdEnum) { + ir_add_error(ira, range->start, buf_sprintf("not an enum type")); + return ira->codegen->builtin_types.entry_invalid; + } + BigInt start_index; bigint_init_bigint(&start_index, &start_value->value.data.x_enum_tag); diff --git a/std/zig/ast.zig b/std/zig/ast.zig index a92555731d6263e774de45b0d9fd038160bd64bc..a452ed890646b1acdba787e7c4cb36e363254a3e 100644 --- a/std/zig/ast.zig +++ b/std/zig/ast.zig @@ -67,6 +67,11 @@ pub const Tree = struct { pub fn tokenLocation(self: &Tree, start_index: usize, token_index: TokenIndex) Location { return self.tokenLocationPtr(start_index, self.tokens.at(token_index)); } + + pub fn dump(self: &Tree) void { + self.root_node.base.dump(0); + } + }; pub const Error = union(enum) { @@ -415,6 +420,20 @@ pub const Node = struct { } } + pub fn dump(self: &Node, indent: usize) void { + { + var i: usize = 0; + while (i < indent) : (i += 1) { + std.debug.warn(" "); + } + } + std.debug.warn("{}\n", @tagName(self.id)); + + var child_i: usize = 0; + while (self.iterate(child_i)) |child| : (child_i += 1) { + child.dump(indent + 2); + } + } pub const Root = struct { base: Node, @@ -426,7 +445,7 @@ pub const Node = struct { pub fn iterate(self: &Root, index: usize) ?&Node { if (index < self.decls.len) { - return self.decls.items[self.decls.len - index - 1]; + return *self.decls.at(index); } return null; } @@ -790,36 +809,37 @@ pub const Node = struct { pub fn iterate(self: &FnProto, index: usize) ?&Node { var i = index; - if (self.body_node) |body_node| { - if (i < 1) return body_node; - i -= 1; - } - - switch (self.return_type) { - // TODO allow this and next prong to share bodies since the types are the same - ReturnType.Explicit => |node| { - if (i < 1) return node; - i -= 1; - }, - ReturnType.InferErrorSet => |node| { - if (i < 1) return node; - i -= 1; - }, - } - - if (self.align_expr) |align_expr| { - if (i < 1) return align_expr; - i -= 1; - } - - if (i < self.params.len) return self.params.items[self.params.len - i - 1]; - i -= self.params.len; - if (self.lib_name) |lib_name| { if (i < 1) return lib_name; i -= 1; } + if (i < self.params.len) return *self.params.at(self.params.len - i - 1); + i -= self.params.len; + + if (self.align_expr) |align_expr| { + if (i < 1) return align_expr; + i -= 1; + } + + switch (self.return_type) { + // TODO allow this and next prong to share bodies since the types are the same + ReturnType.Explicit => |node| { + if (i < 1) return node; + i -= 1; + }, + ReturnType.InferErrorSet => |node| { + if (i < 1) return node; + i -= 1; + }, + } + + if (self.body_node) |body_node| { + if (i < 1) return body_node; + i -= 1; + } + + return null; } @@ -914,7 +934,7 @@ pub const Node = struct { pub fn iterate(self: &Block, index: usize) ?&Node { var i = index; - if (i < self.statements.len) return self.statements.items[i]; + if (i < self.statements.len) return *self.statements.at(i); i -= self.statements.len; return null; @@ -1596,7 +1616,7 @@ pub const Node = struct { i -= 1; switch (self.op) { - Op.Call => |call_info| { + @TagType(Op).Call => |*call_info| { if (i < call_info.params.len) return *call_info.params.at(i); i -= call_info.params.len; }, @@ -1604,7 +1624,7 @@ pub const Node = struct { if (i < 1) return index_expr; i -= 1; }, - Op.Slice => |range| { + @TagType(Op).Slice => |range| { if (i < 1) return range.start; i -= 1; @@ -1613,11 +1633,11 @@ pub const Node = struct { i -= 1; } }, - Op.ArrayInitializer => |exprs| { + Op.ArrayInitializer => |*exprs| { if (i < exprs.len) return *exprs.at(i); i -= exprs.len; }, - Op.StructInitializer => |fields| { + Op.StructInitializer => |*fields| { if (i < fields.len) return *fields.at(i); i -= fields.len; }, diff --git a/std/zig/parse.zig b/std/zig/parse.zig index c96893fd968a496ee42ca4d5792305e6a732a305..f88fdfab62162f4316f7af058ea279b6b3975589 100644 --- a/std/zig/parse.zig +++ b/std/zig/parse.zig @@ -7,9 +7,8 @@ const Token = std.zig.Token; const TokenIndex = ast.TokenIndex; const Error = ast.Error; -/// Returns an AST tree, allocated with the parser's allocator. /// Result should be freed with tree.deinit() when there are -/// no more references to any AST nodes of the tree. +/// no more references to any of the tokens or nodes. pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { var tree_arena = std.heap.ArenaAllocator.init(allocator); errdefer tree_arena.deinit(); @@ -3466,38 +3465,6 @@ fn putBackToken(tok_it: &ast.Tree.TokenList.Iterator, tree: &ast.Tree) void { } } -const RenderAstFrame = struct { - node: &ast.Node, - indent: usize, -}; - -pub fn renderAst(allocator: &mem.Allocator, tree: &const ast.Tree, stream: var) !void { - var stack = std.ArrayList(State).init(allocator); - defer stack.deinit(); - - try stack.append(RenderAstFrame { - .node = &root_node.base, - .indent = 0, - }); - - while (stack.popOrNull()) |frame| { - { - var i: usize = 0; - while (i < frame.indent) : (i += 1) { - try stream.print(" "); - } - } - try stream.print("{}\n", @tagName(frame.node.id)); - var child_i: usize = 0; - while (frame.node.iterate(child_i)) |child| : (child_i += 1) { - try stack.append(RenderAstFrame { - .node = child, - .indent = frame.indent + 2, - }); - } - } -} - test "std.zig.parser" { _ = @import("parser_test.zig"); } -- 2.54.0 From 4c3aa09f2a88f0608c14f5717de21aaa3d56c89e Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 10 May 2018 18:57:57 -0400 Subject: [PATCH 12/47] self hosted compiler: remove unused flag --- src-self-hosted/main.zig | 2 -- 1 file changed, 2 deletions(-) diff --git a/src-self-hosted/main.zig b/src-self-hosted/main.zig index 8dc1d8ce3bfc5252c9202e14af7c39971a353944..22f49e80d95da07cca88ae1ddbf9aed5de594165 100644 --- a/src-self-hosted/main.zig +++ b/src-self-hosted/main.zig @@ -637,14 +637,12 @@ const usage_fmt = \\ \\Options: \\ --help Print this help and exit - \\ --keep-backups Retain backup entries for every file \\ \\ ; const args_fmt_spec = []Flag { Flag.Bool("--help"), - Flag.Bool("--keep-backups"), }; fn cmdFmt(allocator: &Allocator, args: []const []const u8) !void { -- 2.54.0 From 05ecb49bac30041459ae08764edd2aced23d10eb Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 13 May 2018 01:07:55 -0400 Subject: [PATCH 13/47] README: https links --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 1f23e133f84983e98d344ccd938f5baa4db36078..552b784a501f3fe6771a522fd75b81db82ba8bbf 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ -![ZIG](http://ziglang.org/zig-logo.svg) +![ZIG](https://ziglang.org/zig-logo.svg) A programming language designed for robustness, optimality, and clarity. -[ziglang.org](http://ziglang.org) +[ziglang.org](https://ziglang.org) ## Feature Highlights -- 2.54.0 From abcd418451051fe8c3b5c283d1701d101337dde8 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 13 May 2018 14:20:01 -0400 Subject: [PATCH 14/47] std.zig.parse cleanup --- std/zig/parse.zig | 784 ++++++++++++++++++---------------------- std/zig/parser_test.zig | 8 + 2 files changed, 368 insertions(+), 424 deletions(-) diff --git a/std/zig/parse.zig b/std/zig/parse.zig index f88fdfab62162f4316f7af058ea279b6b3975589..3d6429ba71ac03a008ce01443df937680dfaea33 100644 --- a/std/zig/parse.zig +++ b/std/zig/parse.zig @@ -17,15 +17,13 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { defer stack.deinit(); const arena = &tree_arena.allocator; - const root_node = try createNode(arena, ast.Node.Root, - ast.Node.Root { - .base = undefined, - .decls = ast.Node.Root.DeclList.init(arena), - .doc_comments = null, - // initialized when we get the eof token - .eof_token = undefined, - } - ); + const root_node = try arena.construct(ast.Node.Root { + .base = ast.Node { .id = ast.Node.Id.Root }, + .decls = ast.Node.Root.DeclList.init(arena), + .doc_comments = null, + // initialized when we get the eof token + .eof_token = undefined, + }); var tree = ast.Tree { .source = source, @@ -113,15 +111,13 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { continue; }, Token.Id.Keyword_comptime => { - const block = try createNode(arena, ast.Node.Block, - ast.Node.Block { - .base = undefined, - .label = null, - .lbrace = undefined, - .statements = ast.Node.Block.StatementList.init(arena), - .rbrace = undefined, - } - ); + const block = try arena.construct(ast.Node.Block { + .base = ast.Node {.id = ast.Node.Id.Block }, + .label = null, + .lbrace = undefined, + .statements = ast.Node.Block.StatementList.init(arena), + .rbrace = undefined, + }); const node = try arena.construct(ast.Node.Comptime { .base = ast.Node { .id = ast.Node.Id.Comptime, @@ -312,14 +308,12 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { continue; }, Token.Id.Keyword_async => { - const async_node = try createNode(arena, ast.Node.AsyncAttribute, - ast.Node.AsyncAttribute { - .base = undefined, - .async_token = token_index, - .allocator_type = null, - .rangle_bracket = null, - } - ); + const async_node = try arena.construct(ast.Node.AsyncAttribute { + .base = ast.Node {.id = ast.Node.Id.AsyncAttribute }, + .async_token = token_index, + .allocator_type = null, + .rangle_bracket = null, + }); fn_proto.async_attr = async_node; try stack.append(State { @@ -396,27 +390,26 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { const token = nextToken(&tok_it, &tree); const token_index = token.index; const token_ptr = token.ptr; - const node = try createToCtxNode(arena, ctx.opt_ctx, ast.Node.ContainerDecl, - ast.Node.ContainerDecl { - .base = undefined, - .ltoken = ctx.ltoken, - .layout = ctx.layout, - .kind = switch (token_ptr.id) { - Token.Id.Keyword_struct => ast.Node.ContainerDecl.Kind.Struct, - Token.Id.Keyword_union => ast.Node.ContainerDecl.Kind.Union, - Token.Id.Keyword_enum => ast.Node.ContainerDecl.Kind.Enum, - else => { - *(try tree.errors.addOne()) = Error { - .ExpectedAggregateKw = Error.ExpectedAggregateKw { .token = token_index }, - }; - return tree; - }, + const node = try arena.construct(ast.Node.ContainerDecl { + .base = ast.Node {.id = ast.Node.Id.ContainerDecl }, + .ltoken = ctx.ltoken, + .layout = ctx.layout, + .kind = switch (token_ptr.id) { + Token.Id.Keyword_struct => ast.Node.ContainerDecl.Kind.Struct, + Token.Id.Keyword_union => ast.Node.ContainerDecl.Kind.Union, + Token.Id.Keyword_enum => ast.Node.ContainerDecl.Kind.Enum, + else => { + *(try tree.errors.addOne()) = Error { + .ExpectedAggregateKw = Error.ExpectedAggregateKw { .token = token_index }, + }; + return tree; }, - .init_arg_expr = ast.Node.ContainerDecl.InitArg.None, - .fields_and_decls = ast.Node.ContainerDecl.DeclList.init(arena), - .rbrace_token = undefined, - } - ); + }, + .init_arg_expr = ast.Node.ContainerDecl.InitArg.None, + .fields_and_decls = ast.Node.ContainerDecl.DeclList.init(arena), + .rbrace_token = undefined, + }); + ctx.opt_ctx.store(&node.base); stack.append(State { .ContainerDecl = node }) catch unreachable; try stack.append(State { .ExpectToken = Token.Id.LBrace }); @@ -844,15 +837,14 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { const token_ptr = token.ptr; switch (token_ptr.id) { Token.Id.LBrace => { - const block = try createToCtxNode(arena, ctx.opt_ctx, ast.Node.Block, - ast.Node.Block { - .base = undefined, - .label = ctx.label, - .lbrace = token_index, - .statements = ast.Node.Block.StatementList.init(arena), - .rbrace = undefined, - } - ); + const block = try arena.construct(ast.Node.Block { + .base = ast.Node {.id = ast.Node.Id.Block}, + .label = ctx.label, + .lbrace = token_index, + .statements = ast.Node.Block.StatementList.init(arena), + .rbrace = undefined, + }); + ctx.opt_ctx.store(&block.base); stack.append(State { .Block = block }) catch unreachable; continue; }, @@ -957,19 +949,18 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { } }, State.While => |ctx| { - const node = try createToCtxNode(arena, ctx.opt_ctx, ast.Node.While, - ast.Node.While { - .base = undefined, - .label = ctx.label, - .inline_token = ctx.inline_token, - .while_token = ctx.loop_token, - .condition = undefined, - .payload = null, - .continue_expr = null, - .body = undefined, - .@"else" = null, - } - ); + const node = try arena.construct(ast.Node.While { + .base = ast.Node {.id = ast.Node.Id.While }, + .label = ctx.label, + .inline_token = ctx.inline_token, + .while_token = ctx.loop_token, + .condition = undefined, + .payload = null, + .continue_expr = null, + .body = undefined, + .@"else" = null, + }); + ctx.opt_ctx.store(&node.base); stack.append(State { .Else = &node.@"else" }) catch unreachable; try stack.append(State { .Expression = OptionalCtx { .Required = &node.body } }); try stack.append(State { .WhileContinueExpr = &node.continue_expr }); @@ -987,18 +978,17 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { continue; }, State.For => |ctx| { - const node = try createToCtxNode(arena, ctx.opt_ctx, ast.Node.For, - ast.Node.For { - .base = undefined, - .label = ctx.label, - .inline_token = ctx.inline_token, - .for_token = ctx.loop_token, - .array_expr = undefined, - .payload = null, - .body = undefined, - .@"else" = null, - } - ); + const node = try arena.construct(ast.Node.For { + .base = ast.Node {.id = ast.Node.Id.For }, + .label = ctx.label, + .inline_token = ctx.inline_token, + .for_token = ctx.loop_token, + .array_expr = undefined, + .payload = null, + .body = undefined, + .@"else" = null, + }); + ctx.opt_ctx.store(&node.base); stack.append(State { .Else = &node.@"else" }) catch unreachable; try stack.append(State { .Expression = OptionalCtx { .Required = &node.body } }); try stack.append(State { .PointerIndexPayload = OptionalCtx { .Optional = &node.payload } }); @@ -1009,14 +999,12 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { }, State.Else => |dest| { if (eatToken(&tok_it, &tree, Token.Id.Keyword_else)) |else_token| { - const node = try createNode(arena, ast.Node.Else, - ast.Node.Else { - .base = undefined, - .else_token = else_token, - .payload = null, - .body = undefined, - } - ); + const node = try arena.construct(ast.Node.Else { + .base = ast.Node {.id = ast.Node.Id.Else }, + .else_token = else_token, + .payload = null, + .body = undefined, + }); *dest = node; stack.append(State { .Expression = OptionalCtx { .Required = &node.body } }) catch unreachable; @@ -1170,14 +1158,12 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { continue; } - const node = try createNode(arena, ast.Node.AsmOutput, - ast.Node.AsmOutput { - .base = undefined, - .symbolic_name = undefined, - .constraint = undefined, - .kind = undefined, - } - ); + const node = try arena.construct(ast.Node.AsmOutput { + .base = ast.Node {.id = ast.Node.Id.AsmOutput }, + .symbolic_name = undefined, + .constraint = undefined, + .kind = undefined, + }); try items.push(node); stack.append(State { .AsmOutputItems = items }) catch unreachable; @@ -1223,14 +1209,12 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { continue; } - const node = try createNode(arena, ast.Node.AsmInput, - ast.Node.AsmInput { - .base = undefined, - .symbolic_name = undefined, - .constraint = undefined, - .expr = undefined, - } - ); + const node = try arena.construct(ast.Node.AsmInput { + .base = ast.Node {.id = ast.Node.Id.AsmInput }, + .symbolic_name = undefined, + .constraint = undefined, + .expr = undefined, + }); try items.push(node); stack.append(State { .AsmInputItems = items }) catch unreachable; @@ -1668,14 +1652,13 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { continue; } - const node = try createToCtxNode(arena, opt_ctx, ast.Node.Payload, - ast.Node.Payload { - .base = undefined, - .lpipe = token_index, - .error_symbol = undefined, - .rpipe = undefined - } - ); + const node = try arena.construct(ast.Node.Payload { + .base = ast.Node {.id = ast.Node.Id.Payload }, + .lpipe = token_index, + .error_symbol = undefined, + .rpipe = undefined + }); + opt_ctx.store(&node.base); stack.append(State { .ExpectTokenSave = ExpectTokenSave { @@ -1705,15 +1688,14 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { continue; } - const node = try createToCtxNode(arena, opt_ctx, ast.Node.PointerPayload, - ast.Node.PointerPayload { - .base = undefined, - .lpipe = token_index, - .ptr_token = null, - .value_symbol = undefined, - .rpipe = undefined - } - ); + const node = try arena.construct(ast.Node.PointerPayload { + .base = ast.Node {.id = ast.Node.Id.PointerPayload }, + .lpipe = token_index, + .ptr_token = null, + .value_symbol = undefined, + .rpipe = undefined + }); + opt_ctx.store(&node.base); try stack.append(State { .ExpectTokenSave = ExpectTokenSave { @@ -1749,16 +1731,15 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { continue; } - const node = try createToCtxNode(arena, opt_ctx, ast.Node.PointerIndexPayload, - ast.Node.PointerIndexPayload { - .base = undefined, - .lpipe = token_index, - .ptr_token = null, - .value_symbol = undefined, - .index_symbol = null, - .rpipe = undefined - } - ); + const node = try arena.construct(ast.Node.PointerIndexPayload { + .base = ast.Node {.id = ast.Node.Id.PointerIndexPayload }, + .lpipe = token_index, + .ptr_token = null, + .value_symbol = undefined, + .index_symbol = null, + .rpipe = undefined + }); + opt_ctx.store(&node.base); stack.append(State { .ExpectTokenSave = ExpectTokenSave { @@ -1785,14 +1766,13 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { const token_ptr = token.ptr; switch (token_ptr.id) { Token.Id.Keyword_return, Token.Id.Keyword_break, Token.Id.Keyword_continue => { - const node = try createToCtxNode(arena, opt_ctx, ast.Node.ControlFlowExpression, - ast.Node.ControlFlowExpression { - .base = undefined, - .ltoken = token_index, - .kind = undefined, - .rhs = null, - } - ); + const node = try arena.construct(ast.Node.ControlFlowExpression { + .base = ast.Node {.id = ast.Node.Id.ControlFlowExpression }, + .ltoken = token_index, + .kind = undefined, + .rhs = null, + }); + opt_ctx.store(&node.base); stack.append(State { .Expression = OptionalCtx { .Optional = &node.rhs } }) catch unreachable; @@ -1815,19 +1795,18 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { continue; }, Token.Id.Keyword_try, Token.Id.Keyword_cancel, Token.Id.Keyword_resume => { - const node = try createToCtxNode(arena, opt_ctx, ast.Node.PrefixOp, - ast.Node.PrefixOp { - .base = undefined, - .op_token = token_index, - .op = switch (token_ptr.id) { - Token.Id.Keyword_try => ast.Node.PrefixOp.Op { .Try = void{} }, - Token.Id.Keyword_cancel => ast.Node.PrefixOp.Op { .Cancel = void{} }, - Token.Id.Keyword_resume => ast.Node.PrefixOp.Op { .Resume = void{} }, - else => unreachable, - }, - .rhs = undefined, - } - ); + const node = try arena.construct(ast.Node.PrefixOp { + .base = ast.Node {.id = ast.Node.Id.PrefixOp }, + .op_token = token_index, + .op = switch (token_ptr.id) { + Token.Id.Keyword_try => ast.Node.PrefixOp.Op { .Try = void{} }, + Token.Id.Keyword_cancel => ast.Node.PrefixOp.Op { .Cancel = void{} }, + Token.Id.Keyword_resume => ast.Node.PrefixOp.Op { .Resume = void{} }, + else => unreachable, + }, + .rhs = undefined, + }); + opt_ctx.store(&node.base); stack.append(State { .Expression = OptionalCtx { .Required = &node.rhs } }) catch unreachable; continue; @@ -1850,15 +1829,14 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { const lhs = opt_ctx.get() ?? continue; if (eatToken(&tok_it, &tree, Token.Id.Ellipsis3)) |ellipsis3| { - const node = try createToCtxNode(arena, opt_ctx, ast.Node.InfixOp, - ast.Node.InfixOp { - .base = undefined, - .lhs = lhs, - .op_token = ellipsis3, - .op = ast.Node.InfixOp.Op.Range, - .rhs = undefined, - } - ); + const node = try arena.construct(ast.Node.InfixOp { + .base = ast.Node {.id = ast.Node.Id.InfixOp }, + .lhs = lhs, + .op_token = ellipsis3, + .op = ast.Node.InfixOp.Op.Range, + .rhs = undefined, + }); + opt_ctx.store(&node.base); stack.append(State { .Expression = OptionalCtx { .Required = &node.rhs } }) catch unreachable; continue; } @@ -1876,15 +1854,14 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { const token_index = token.index; const token_ptr = token.ptr; if (tokenIdToAssignment(token_ptr.id)) |ass_id| { - const node = try createToCtxNode(arena, opt_ctx, ast.Node.InfixOp, - ast.Node.InfixOp { - .base = undefined, - .lhs = lhs, - .op_token = token_index, - .op = ass_id, - .rhs = undefined, - } - ); + const node = try arena.construct(ast.Node.InfixOp { + .base = ast.Node {.id = ast.Node.Id.InfixOp }, + .lhs = lhs, + .op_token = token_index, + .op = ass_id, + .rhs = undefined, + }); + opt_ctx.store(&node.base); stack.append(State { .AssignmentExpressionEnd = opt_ctx.toRequired() }) catch unreachable; try stack.append(State { .Expression = OptionalCtx { .Required = &node.rhs } }); continue; @@ -1907,15 +1884,14 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { const token_index = token.index; const token_ptr = token.ptr; if (tokenIdToUnwrapExpr(token_ptr.id)) |unwrap_id| { - const node = try createToCtxNode(arena, opt_ctx, ast.Node.InfixOp, - ast.Node.InfixOp { - .base = undefined, - .lhs = lhs, - .op_token = token_index, - .op = unwrap_id, - .rhs = undefined, - } - ); + const node = try arena.construct(ast.Node.InfixOp { + .base = ast.Node {.id = ast.Node.Id.InfixOp }, + .lhs = lhs, + .op_token = token_index, + .op = unwrap_id, + .rhs = undefined, + }); + opt_ctx.store(&node.base); stack.append(State { .UnwrapExpressionEnd = opt_ctx.toRequired() }) catch unreachable; try stack.append(State { .Expression = OptionalCtx { .Required = &node.rhs } }); @@ -1940,15 +1916,14 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { const lhs = opt_ctx.get() ?? continue; if (eatToken(&tok_it, &tree, Token.Id.Keyword_or)) |or_token| { - const node = try createToCtxNode(arena, opt_ctx, ast.Node.InfixOp, - ast.Node.InfixOp { - .base = undefined, - .lhs = lhs, - .op_token = or_token, - .op = ast.Node.InfixOp.Op.BoolOr, - .rhs = undefined, - } - ); + const node = try arena.construct(ast.Node.InfixOp { + .base = ast.Node {.id = ast.Node.Id.InfixOp }, + .lhs = lhs, + .op_token = or_token, + .op = ast.Node.InfixOp.Op.BoolOr, + .rhs = undefined, + }); + opt_ctx.store(&node.base); stack.append(State { .BoolOrExpressionEnd = opt_ctx.toRequired() }) catch unreachable; try stack.append(State { .BoolAndExpressionBegin = OptionalCtx { .Required = &node.rhs } }); continue; @@ -1965,15 +1940,14 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { const lhs = opt_ctx.get() ?? continue; if (eatToken(&tok_it, &tree, Token.Id.Keyword_and)) |and_token| { - const node = try createToCtxNode(arena, opt_ctx, ast.Node.InfixOp, - ast.Node.InfixOp { - .base = undefined, - .lhs = lhs, - .op_token = and_token, - .op = ast.Node.InfixOp.Op.BoolAnd, - .rhs = undefined, - } - ); + const node = try arena.construct(ast.Node.InfixOp { + .base = ast.Node {.id = ast.Node.Id.InfixOp }, + .lhs = lhs, + .op_token = and_token, + .op = ast.Node.InfixOp.Op.BoolAnd, + .rhs = undefined, + }); + opt_ctx.store(&node.base); stack.append(State { .BoolAndExpressionEnd = opt_ctx.toRequired() }) catch unreachable; try stack.append(State { .ComparisonExpressionBegin = OptionalCtx { .Required = &node.rhs } }); continue; @@ -1993,15 +1967,14 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { const token_index = token.index; const token_ptr = token.ptr; if (tokenIdToComparison(token_ptr.id)) |comp_id| { - const node = try createToCtxNode(arena, opt_ctx, ast.Node.InfixOp, - ast.Node.InfixOp { - .base = undefined, - .lhs = lhs, - .op_token = token_index, - .op = comp_id, - .rhs = undefined, - } - ); + const node = try arena.construct(ast.Node.InfixOp { + .base = ast.Node {.id = ast.Node.Id.InfixOp }, + .lhs = lhs, + .op_token = token_index, + .op = comp_id, + .rhs = undefined, + }); + opt_ctx.store(&node.base); stack.append(State { .ComparisonExpressionEnd = opt_ctx.toRequired() }) catch unreachable; try stack.append(State { .BinaryOrExpressionBegin = OptionalCtx { .Required = &node.rhs } }); continue; @@ -2021,15 +1994,14 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { const lhs = opt_ctx.get() ?? continue; if (eatToken(&tok_it, &tree, Token.Id.Pipe)) |pipe| { - const node = try createToCtxNode(arena, opt_ctx, ast.Node.InfixOp, - ast.Node.InfixOp { - .base = undefined, - .lhs = lhs, - .op_token = pipe, - .op = ast.Node.InfixOp.Op.BitOr, - .rhs = undefined, - } - ); + const node = try arena.construct(ast.Node.InfixOp { + .base = ast.Node {.id = ast.Node.Id.InfixOp }, + .lhs = lhs, + .op_token = pipe, + .op = ast.Node.InfixOp.Op.BitOr, + .rhs = undefined, + }); + opt_ctx.store(&node.base); stack.append(State { .BinaryOrExpressionEnd = opt_ctx.toRequired() }) catch unreachable; try stack.append(State { .BinaryXorExpressionBegin = OptionalCtx { .Required = &node.rhs } }); continue; @@ -2046,15 +2018,14 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { const lhs = opt_ctx.get() ?? continue; if (eatToken(&tok_it, &tree, Token.Id.Caret)) |caret| { - const node = try createToCtxNode(arena, opt_ctx, ast.Node.InfixOp, - ast.Node.InfixOp { - .base = undefined, - .lhs = lhs, - .op_token = caret, - .op = ast.Node.InfixOp.Op.BitXor, - .rhs = undefined, - } - ); + const node = try arena.construct(ast.Node.InfixOp { + .base = ast.Node {.id = ast.Node.Id.InfixOp }, + .lhs = lhs, + .op_token = caret, + .op = ast.Node.InfixOp.Op.BitXor, + .rhs = undefined, + }); + opt_ctx.store(&node.base); stack.append(State { .BinaryXorExpressionEnd = opt_ctx.toRequired() }) catch unreachable; try stack.append(State { .BinaryAndExpressionBegin = OptionalCtx { .Required = &node.rhs } }); continue; @@ -2071,15 +2042,14 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { const lhs = opt_ctx.get() ?? continue; if (eatToken(&tok_it, &tree, Token.Id.Ampersand)) |ampersand| { - const node = try createToCtxNode(arena, opt_ctx, ast.Node.InfixOp, - ast.Node.InfixOp { - .base = undefined, - .lhs = lhs, - .op_token = ampersand, - .op = ast.Node.InfixOp.Op.BitAnd, - .rhs = undefined, - } - ); + const node = try arena.construct(ast.Node.InfixOp { + .base = ast.Node {.id = ast.Node.Id.InfixOp }, + .lhs = lhs, + .op_token = ampersand, + .op = ast.Node.InfixOp.Op.BitAnd, + .rhs = undefined, + }); + opt_ctx.store(&node.base); stack.append(State { .BinaryAndExpressionEnd = opt_ctx.toRequired() }) catch unreachable; try stack.append(State { .BitShiftExpressionBegin = OptionalCtx { .Required = &node.rhs } }); continue; @@ -2099,15 +2069,14 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { const token_index = token.index; const token_ptr = token.ptr; if (tokenIdToBitShift(token_ptr.id)) |bitshift_id| { - const node = try createToCtxNode(arena, opt_ctx, ast.Node.InfixOp, - ast.Node.InfixOp { - .base = undefined, - .lhs = lhs, - .op_token = token_index, - .op = bitshift_id, - .rhs = undefined, - } - ); + const node = try arena.construct(ast.Node.InfixOp { + .base = ast.Node {.id = ast.Node.Id.InfixOp }, + .lhs = lhs, + .op_token = token_index, + .op = bitshift_id, + .rhs = undefined, + }); + opt_ctx.store(&node.base); stack.append(State { .BitShiftExpressionEnd = opt_ctx.toRequired() }) catch unreachable; try stack.append(State { .AdditionExpressionBegin = OptionalCtx { .Required = &node.rhs } }); continue; @@ -2130,15 +2099,14 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { const token_index = token.index; const token_ptr = token.ptr; if (tokenIdToAddition(token_ptr.id)) |add_id| { - const node = try createToCtxNode(arena, opt_ctx, ast.Node.InfixOp, - ast.Node.InfixOp { - .base = undefined, - .lhs = lhs, - .op_token = token_index, - .op = add_id, - .rhs = undefined, - } - ); + const node = try arena.construct(ast.Node.InfixOp { + .base = ast.Node {.id = ast.Node.Id.InfixOp }, + .lhs = lhs, + .op_token = token_index, + .op = add_id, + .rhs = undefined, + }); + opt_ctx.store(&node.base); stack.append(State { .AdditionExpressionEnd = opt_ctx.toRequired() }) catch unreachable; try stack.append(State { .MultiplyExpressionBegin = OptionalCtx { .Required = &node.rhs } }); continue; @@ -2161,15 +2129,14 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { const token_index = token.index; const token_ptr = token.ptr; if (tokenIdToMultiply(token_ptr.id)) |mult_id| { - const node = try createToCtxNode(arena, opt_ctx, ast.Node.InfixOp, - ast.Node.InfixOp { - .base = undefined, - .lhs = lhs, - .op_token = token_index, - .op = mult_id, - .rhs = undefined, - } - ); + const node = try arena.construct(ast.Node.InfixOp { + .base = ast.Node {.id = ast.Node.Id.InfixOp }, + .lhs = lhs, + .op_token = token_index, + .op = mult_id, + .rhs = undefined, + }); + opt_ctx.store(&node.base); stack.append(State { .MultiplyExpressionEnd = opt_ctx.toRequired() }) catch unreachable; try stack.append(State { .CurlySuffixExpressionBegin = OptionalCtx { .Required = &node.rhs } }); continue; @@ -2211,16 +2178,15 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { continue; } - const node = try createToCtxNode(arena, opt_ctx, ast.Node.SuffixOp, - ast.Node.SuffixOp { - .base = undefined, - .lhs = lhs, - .op = ast.Node.SuffixOp.Op { - .ArrayInitializer = ast.Node.SuffixOp.Op.InitList.init(arena), - }, - .rtoken = undefined, - } - ); + const node = try arena.construct(ast.Node.SuffixOp { + .base = ast.Node {.id = ast.Node.Id.SuffixOp }, + .lhs = lhs, + .op = ast.Node.SuffixOp.Op { + .ArrayInitializer = ast.Node.SuffixOp.Op.InitList.init(arena), + }, + .rtoken = undefined, + }); + opt_ctx.store(&node.base); stack.append(State { .CurlySuffixExpressionEnd = opt_ctx.toRequired() }) catch unreachable; try stack.append(State { .IfToken = Token.Id.LBrace }); try stack.append(State { @@ -2243,15 +2209,14 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { const lhs = opt_ctx.get() ?? continue; if (eatToken(&tok_it, &tree, Token.Id.Bang)) |bang| { - const node = try createToCtxNode(arena, opt_ctx, ast.Node.InfixOp, - ast.Node.InfixOp { - .base = undefined, - .lhs = lhs, - .op_token = bang, - .op = ast.Node.InfixOp.Op.ErrorUnion, - .rhs = undefined, - } - ); + const node = try arena.construct(ast.Node.InfixOp { + .base = ast.Node {.id = ast.Node.Id.InfixOp }, + .lhs = lhs, + .op_token = bang, + .op = ast.Node.InfixOp.Op.ErrorUnion, + .rhs = undefined, + }); + opt_ctx.store(&node.base); stack.append(State { .TypeExprEnd = opt_ctx.toRequired() }) catch unreachable; try stack.append(State { .PrefixOpExpression = OptionalCtx { .Required = &node.rhs } }); continue; @@ -2263,25 +2228,22 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { const token_index = token.index; const token_ptr = token.ptr; if (tokenIdToPrefixOp(token_ptr.id)) |prefix_id| { - var node = try createToCtxNode(arena, opt_ctx, ast.Node.PrefixOp, - ast.Node.PrefixOp { - .base = undefined, - .op_token = token_index, - .op = prefix_id, - .rhs = undefined, - } - ); + var node = try arena.construct(ast.Node.PrefixOp { + .base = ast.Node {.id = ast.Node.Id.PrefixOp }, + .op_token = token_index, + .op = prefix_id, + .rhs = undefined, + }); + opt_ctx.store(&node.base); // Treat '**' token as two derefs if (token_ptr.id == Token.Id.AsteriskAsterisk) { - const child = try createNode(arena, ast.Node.PrefixOp, - ast.Node.PrefixOp { - .base = undefined, - .op_token = token_index, - .op = prefix_id, - .rhs = undefined, - } - ); + const child = try arena.construct(ast.Node.PrefixOp { + .base = ast.Node {.id = ast.Node.Id.PrefixOp}, + .op_token = token_index, + .op = prefix_id, + .rhs = undefined, + }); node.rhs = &child.base; node = child; } @@ -2300,14 +2262,12 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { State.SuffixOpExpressionBegin => |opt_ctx| { if (eatToken(&tok_it, &tree, Token.Id.Keyword_async)) |async_token| { - const async_node = try createNode(arena, ast.Node.AsyncAttribute, - ast.Node.AsyncAttribute { - .base = undefined, - .async_token = async_token, - .allocator_type = null, - .rangle_bracket = null, - } - ); + const async_node = try arena.construct(ast.Node.AsyncAttribute { + .base = ast.Node {.id = ast.Node.Id.AsyncAttribute}, + .async_token = async_token, + .allocator_type = null, + .rangle_bracket = null, + }); stack.append(State { .AsyncEnd = AsyncEndCtx { .ctx = opt_ctx, @@ -2333,19 +2293,19 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { const token_ptr = token.ptr; switch (token_ptr.id) { Token.Id.LParen => { - const node = try createToCtxNode(arena, opt_ctx, ast.Node.SuffixOp, - ast.Node.SuffixOp { - .base = undefined, - .lhs = lhs, - .op = ast.Node.SuffixOp.Op { - .Call = ast.Node.SuffixOp.Op.Call { - .params = ast.Node.SuffixOp.Op.Call.ParamList.init(arena), - .async_attr = null, - } - }, - .rtoken = undefined, - } - ); + const node = try arena.construct(ast.Node.SuffixOp { + .base = ast.Node {.id = ast.Node.Id.SuffixOp }, + .lhs = lhs, + .op = ast.Node.SuffixOp.Op { + .Call = ast.Node.SuffixOp.Op.Call { + .params = ast.Node.SuffixOp.Op.Call.ParamList.init(arena), + .async_attr = null, + } + }, + .rtoken = undefined, + }); + opt_ctx.store(&node.base); + stack.append(State { .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable; try stack.append(State { .ExprListItemOrEnd = ExprListCtx { @@ -2357,31 +2317,31 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { continue; }, Token.Id.LBracket => { - const node = try createToCtxNode(arena, opt_ctx, ast.Node.SuffixOp, - ast.Node.SuffixOp { - .base = undefined, - .lhs = lhs, - .op = ast.Node.SuffixOp.Op { - .ArrayAccess = undefined, - }, - .rtoken = undefined - } - ); + const node = try arena.construct(ast.Node.SuffixOp { + .base = ast.Node {.id = ast.Node.Id.SuffixOp }, + .lhs = lhs, + .op = ast.Node.SuffixOp.Op { + .ArrayAccess = undefined, + }, + .rtoken = undefined + }); + opt_ctx.store(&node.base); + stack.append(State { .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable; try stack.append(State { .SliceOrArrayAccess = node }); try stack.append(State { .Expression = OptionalCtx { .Required = &node.op.ArrayAccess }}); continue; }, Token.Id.Period => { - const node = try createToCtxNode(arena, opt_ctx, ast.Node.InfixOp, - ast.Node.InfixOp { - .base = undefined, - .lhs = lhs, - .op_token = token_index, - .op = ast.Node.InfixOp.Op.Period, - .rhs = undefined, - } - ); + const node = try arena.construct(ast.Node.InfixOp { + .base = ast.Node {.id = ast.Node.Id.InfixOp }, + .lhs = lhs, + .op_token = token_index, + .op = ast.Node.InfixOp.Op.Period, + .rhs = undefined, + }); + opt_ctx.store(&node.base); + stack.append(State { .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable; try stack.append(State { .Identifier = OptionalCtx { .Required = &node.rhs } }); continue; @@ -2461,14 +2421,14 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { continue; }, Token.Id.LParen => { - const node = try createToCtxNode(arena, opt_ctx, ast.Node.GroupedExpression, - ast.Node.GroupedExpression { - .base = undefined, - .lparen = token.index, - .expr = undefined, - .rparen = undefined, - } - ); + const node = try arena.construct(ast.Node.GroupedExpression { + .base = ast.Node {.id = ast.Node.Id.GroupedExpression }, + .lparen = token.index, + .expr = undefined, + .rparen = undefined, + }); + opt_ctx.store(&node.base); + stack.append(State { .ExpectTokenSave = ExpectTokenSave { .id = Token.Id.RParen, @@ -2479,14 +2439,14 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { continue; }, Token.Id.Builtin => { - const node = try createToCtxNode(arena, opt_ctx, ast.Node.BuiltinCall, - ast.Node.BuiltinCall { - .base = undefined, - .builtin_token = token.index, - .params = ast.Node.BuiltinCall.ParamList.init(arena), - .rparen_token = undefined, - } - ); + const node = try arena.construct(ast.Node.BuiltinCall { + .base = ast.Node {.id = ast.Node.Id.BuiltinCall }, + .builtin_token = token.index, + .params = ast.Node.BuiltinCall.ParamList.init(arena), + .rparen_token = undefined, + }); + opt_ctx.store(&node.base); + stack.append(State { .ExprListItemOrEnd = ExprListCtx { .list = &node.params, @@ -2498,14 +2458,14 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { continue; }, Token.Id.LBracket => { - const node = try createToCtxNode(arena, opt_ctx, ast.Node.PrefixOp, - ast.Node.PrefixOp { - .base = undefined, - .op_token = token.index, - .op = undefined, - .rhs = undefined, - } - ); + const node = try arena.construct(ast.Node.PrefixOp { + .base = ast.Node {.id = ast.Node.Id.PrefixOp }, + .op_token = token.index, + .op = undefined, + .rhs = undefined, + }); + opt_ctx.store(&node.base); + stack.append(State { .SliceOrArrayType = node }) catch unreachable; continue; }, @@ -2611,18 +2571,18 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { continue; }, Token.Id.Keyword_asm => { - const node = try createToCtxNode(arena, opt_ctx, ast.Node.Asm, - ast.Node.Asm { - .base = undefined, - .asm_token = token.index, - .volatile_token = null, - .template = undefined, - .outputs = ast.Node.Asm.OutputList.init(arena), - .inputs = ast.Node.Asm.InputList.init(arena), - .clobbers = ast.Node.Asm.ClobberList.init(arena), - .rparen = undefined, - } - ); + const node = try arena.construct(ast.Node.Asm { + .base = ast.Node {.id = ast.Node.Id.Asm }, + .asm_token = token.index, + .volatile_token = null, + .template = undefined, + .outputs = ast.Node.Asm.OutputList.init(arena), + .inputs = ast.Node.Asm.InputList.init(arena), + .clobbers = ast.Node.Asm.ClobberList.init(arena), + .rparen = undefined, + }); + opt_ctx.store(&node.base); + stack.append(State { .ExpectTokenSave = ExpectTokenSave { .id = Token.Id.RParen, @@ -3155,31 +3115,29 @@ fn parseBlockExpr(stack: &std.ArrayList(State), arena: &mem.Allocator, ctx: &con token_ptr: &const Token, token_index: TokenIndex) !bool { switch (token_ptr.id) { Token.Id.Keyword_suspend => { - const node = try createToCtxNode(arena, ctx, ast.Node.Suspend, - ast.Node.Suspend { - .base = undefined, - .label = null, - .suspend_token = token_index, - .payload = null, - .body = null, - } - ); + const node = try arena.construct(ast.Node.Suspend { + .base = ast.Node {.id = ast.Node.Id.Suspend }, + .label = null, + .suspend_token = token_index, + .payload = null, + .body = null, + }); + ctx.store(&node.base); stack.append(State { .SuspendBody = node }) catch unreachable; try stack.append(State { .Payload = OptionalCtx { .Optional = &node.payload } }); return true; }, Token.Id.Keyword_if => { - const node = try createToCtxNode(arena, ctx, ast.Node.If, - ast.Node.If { - .base = undefined, - .if_token = token_index, - .condition = undefined, - .payload = null, - .body = undefined, - .@"else" = null, - } - ); + const node = try arena.construct(ast.Node.If { + .base = ast.Node {.id = ast.Node.Id.If }, + .if_token = token_index, + .condition = undefined, + .payload = null, + .body = undefined, + .@"else" = null, + }); + ctx.store(&node.base); stack.append(State { .Else = &node.@"else" }) catch unreachable; try stack.append(State { .Expression = OptionalCtx { .Required = &node.body } }); @@ -3236,14 +3194,14 @@ fn parseBlockExpr(stack: &std.ArrayList(State), arena: &mem.Allocator, ctx: &con return true; }, Token.Id.Keyword_comptime => { - const node = try createToCtxNode(arena, ctx, ast.Node.Comptime, - ast.Node.Comptime { - .base = undefined, - .comptime_token = token_index, - .expr = undefined, - .doc_comments = null, - } - ); + const node = try arena.construct(ast.Node.Comptime { + .base = ast.Node {.id = ast.Node.Id.Comptime }, + .comptime_token = token_index, + .expr = undefined, + .doc_comments = null, + }); + ctx.store(&node.base); + try stack.append(State { .Expression = OptionalCtx { .Required = &node.expr } }); return true; }, @@ -3390,33 +3348,11 @@ fn tokenIdToPrefixOp(id: @TagType(Token.Id)) ?ast.Node.PrefixOp.Op { }; } -fn createNode(arena: &mem.Allocator, comptime T: type, init_to: &const T) !&T { - const node = try arena.create(T); - *node = *init_to; - node.base = blk: { - const id = ast.Node.typeToId(T); - break :blk ast.Node { - .id = id, - }; - }; - - return node; -} - -fn createToCtxNode(arena: &mem.Allocator, opt_ctx: &const OptionalCtx, comptime T: type, init_to: &const T) !&T { - const node = try createNode(arena, T, init_to); - opt_ctx.store(&node.base); - - return node; -} - fn createLiteral(arena: &mem.Allocator, comptime T: type, token_index: TokenIndex) !&T { - return createNode(arena, T, - T { - .base = undefined, - .token = token_index, - } - ); + return arena.construct(T { + .base = ast.Node {.id = ast.Node.typeToId(T)}, + .token = token_index, + }); } fn createToCtxLiteral(arena: &mem.Allocator, opt_ctx: &const OptionalCtx, comptime T: type, token_index: TokenIndex) !&T { diff --git a/std/zig/parser_test.zig b/std/zig/parser_test.zig index 29b231a4dbc3a98482e895af971b8b59e3d7293f..0f0ea5fdf149913ef3427bf7cf970804c14b560c 100644 --- a/std/zig/parser_test.zig +++ b/std/zig/parser_test.zig @@ -1,3 +1,11 @@ +//test "zig fmt: same-line doc comment on variable declaration" { +// try testCanonical( +// \\pub const MAP_ANONYMOUS = 0x1000; /// allocated from memory, swap space +// \\pub const MAP_FILE = 0x0000; /// map from file (default) +// \\ +// ); +//} + test "zig fmt: same-line comment after a statement" { try testCanonical( \\test "" { -- 2.54.0 From 04bca58a3a3a85eeaa36ab4c2cc0881347e123b0 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 15 May 2018 00:33:34 -0400 Subject: [PATCH 15/47] zig fmt: preserve same line doc comments on var decls --- std/zig/parse.zig | 66 ++++++++++++++++++++++++++++------------- std/zig/parser_test.zig | 20 ++++++++----- 2 files changed, 58 insertions(+), 28 deletions(-) diff --git a/std/zig/parse.zig b/std/zig/parse.zig index 3d6429ba71ac03a008ce01443df937680dfaea33..f2376f0df310261df14f7b1579a5281f2996f7b0 100644 --- a/std/zig/parse.zig +++ b/std/zig/parse.zig @@ -640,12 +640,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { switch (token_ptr.id) { Token.Id.Equal => { var_decl.eq_token = token_index; - stack.append(State { - .ExpectTokenSave = ExpectTokenSave { - .id = Token.Id.Semicolon, - .ptr = &var_decl.semicolon_token, - }, - }) catch unreachable; + stack.append(State { .VarDeclSemiColon = var_decl }) catch unreachable; try stack.append(State { .Expression = OptionalCtx { .RequiredNull = &var_decl.init_node } }); continue; }, @@ -662,6 +657,30 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { } }, + State.VarDeclSemiColon => |var_decl| { + const semicolon_token = nextToken(&tok_it, &tree); + + if (semicolon_token.ptr.id != Token.Id.Semicolon) { + *(try tree.errors.addOne()) = Error { + .ExpectedToken = Error.ExpectedToken { + .token = semicolon_token.index, + .expected_id = Token.Id.Semicolon, + }, + }; + return tree; + } + + var_decl.semicolon_token = semicolon_token.index; + + if (eatToken(&tok_it, &tree, Token.Id.DocComment)) |doc_comment_token| { + const loc = tree.tokenLocation(semicolon_token.ptr.end, doc_comment_token); + if (loc.line == 0) { + try pushDocComment(arena, doc_comment_token, &var_decl.doc_comments); + } else { + putBackToken(&tok_it, &tree); + } + } + }, State.FnDef => |fn_proto| { const token = nextToken(&tok_it, &tree); @@ -2938,6 +2957,7 @@ const State = union(enum) { VarDecl: VarDeclCtx, VarDeclAlign: &ast.Node.VarDecl, VarDeclEq: &ast.Node.VarDecl, + VarDeclSemiColon: &ast.Node.VarDecl, FnDef: &ast.Node.FnProto, FnProto: &ast.Node.FnProto, @@ -3042,25 +3062,29 @@ const State = union(enum) { OptionalTokenSave: OptionalTokenSave, }; +fn pushDocComment(arena: &mem.Allocator, line_comment: TokenIndex, result: &?&ast.Node.DocComment) !void { + const node = blk: { + if (*result) |comment_node| { + break :blk comment_node; + } else { + const comment_node = try arena.construct(ast.Node.DocComment { + .base = ast.Node { + .id = ast.Node.Id.DocComment, + }, + .lines = ast.Node.DocComment.LineList.init(arena), + }); + *result = comment_node; + break :blk comment_node; + } + }; + try node.lines.push(line_comment); +} + fn eatDocComments(arena: &mem.Allocator, tok_it: &ast.Tree.TokenList.Iterator, tree: &ast.Tree) !?&ast.Node.DocComment { var result: ?&ast.Node.DocComment = null; while (true) { if (eatToken(tok_it, tree, Token.Id.DocComment)) |line_comment| { - const node = blk: { - if (result) |comment_node| { - break :blk comment_node; - } else { - const comment_node = try arena.construct(ast.Node.DocComment { - .base = ast.Node { - .id = ast.Node.Id.DocComment, - }, - .lines = ast.Node.DocComment.LineList.init(arena), - }); - result = comment_node; - break :blk comment_node; - } - }; - try node.lines.push(line_comment); + try pushDocComment(arena, line_comment, &result); continue; } break; diff --git a/std/zig/parser_test.zig b/std/zig/parser_test.zig index 0f0ea5fdf149913ef3427bf7cf970804c14b560c..f95ecfaee357b83c6aca08cebc14bbdeb7e073b1 100644 --- a/std/zig/parser_test.zig +++ b/std/zig/parser_test.zig @@ -1,10 +1,16 @@ -//test "zig fmt: same-line doc comment on variable declaration" { -// try testCanonical( -// \\pub const MAP_ANONYMOUS = 0x1000; /// allocated from memory, swap space -// \\pub const MAP_FILE = 0x0000; /// map from file (default) -// \\ -// ); -//} +test "zig fmt: same-line doc comment on variable declaration" { + try testTransform( + \\pub const MAP_ANONYMOUS = 0x1000; /// allocated from memory, swap space + \\pub const MAP_FILE = 0x0000; /// map from file (default) + \\ + , + \\/// allocated from memory, swap space + \\pub const MAP_ANONYMOUS = 0x1000; + \\/// map from file (default) + \\pub const MAP_FILE = 0x0000; + \\ + ); +} test "zig fmt: same-line comment after a statement" { try testCanonical( -- 2.54.0 From 74b10c08d1bd0b64aa8175dff6dec178c7c3bbee Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 15 May 2018 14:11:41 -0400 Subject: [PATCH 16/47] fix @typeInfo not setting a field to comptime --- src/ir.cpp | 1 + test/cases/type_info.zig | 305 ++++++++++++++++++++++----------------- 2 files changed, 171 insertions(+), 135 deletions(-) diff --git a/src/ir.cpp b/src/ir.cpp index 31d22ca82a8ecc43c5333ba7b61d61e2d0e91297..cade660651b4b25a9f7c7ac942a646c398de3803 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -16549,6 +16549,7 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t { size_t byte_offset = LLVMOffsetOfElement(ira->codegen->target_data_ref, type_entry->type_ref, struct_field->gen_index); inner_fields[1].data.x_maybe = create_const_vals(1); + inner_fields[1].data.x_maybe->special = ConstValSpecialStatic; inner_fields[1].data.x_maybe->type = ira->codegen->builtin_types.entry_usize; bigint_init_unsigned(&inner_fields[1].data.x_maybe->data.x_bigint, byte_offset); } diff --git a/test/cases/type_info.zig b/test/cases/type_info.zig index f10703e3ee678de73f5738384abb8ca1252389e5..7bf1e68180592b1dc0ec762b240260d585234fe4 100644 --- a/test/cases/type_info.zig +++ b/test/cases/type_info.zig @@ -4,167 +4,199 @@ const TypeInfo = @import("builtin").TypeInfo; const TypeId = @import("builtin").TypeId; test "type info: tag type, void info" { - comptime { - assert(@TagType(TypeInfo) == TypeId); - const void_info = @typeInfo(void); - assert(TypeId(void_info) == TypeId.Void); - assert(void_info.Void == {}); - } + testBasic(); + comptime testBasic(); +} + +fn testBasic() void { + assert(@TagType(TypeInfo) == TypeId); + const void_info = @typeInfo(void); + assert(TypeId(void_info) == TypeId.Void); + assert(void_info.Void == {}); } test "type info: integer, floating point type info" { - comptime { - const u8_info = @typeInfo(u8); - assert(TypeId(u8_info) == TypeId.Int); - assert(!u8_info.Int.is_signed); - assert(u8_info.Int.bits == 8); + testIntFloat(); + comptime testIntFloat(); +} - const f64_info = @typeInfo(f64); - assert(TypeId(f64_info) == TypeId.Float); - assert(f64_info.Float.bits == 64); - } +fn testIntFloat() void { + const u8_info = @typeInfo(u8); + assert(TypeId(u8_info) == TypeId.Int); + assert(!u8_info.Int.is_signed); + assert(u8_info.Int.bits == 8); + + const f64_info = @typeInfo(f64); + assert(TypeId(f64_info) == TypeId.Float); + assert(f64_info.Float.bits == 64); } test "type info: pointer type info" { - comptime { - const u32_ptr_info = @typeInfo(&u32); - assert(TypeId(u32_ptr_info) == TypeId.Pointer); - assert(u32_ptr_info.Pointer.is_const == false); - assert(u32_ptr_info.Pointer.is_volatile == false); - assert(u32_ptr_info.Pointer.alignment == 4); - assert(u32_ptr_info.Pointer.child == u32); - } + testPointer(); + comptime testPointer(); +} + +fn testPointer() void { + const u32_ptr_info = @typeInfo(&u32); + assert(TypeId(u32_ptr_info) == TypeId.Pointer); + assert(u32_ptr_info.Pointer.is_const == false); + assert(u32_ptr_info.Pointer.is_volatile == false); + assert(u32_ptr_info.Pointer.alignment == 4); + assert(u32_ptr_info.Pointer.child == u32); } test "type info: slice type info" { - comptime { - const u32_slice_info = @typeInfo([]u32); - assert(TypeId(u32_slice_info) == TypeId.Slice); - assert(u32_slice_info.Slice.is_const == false); - assert(u32_slice_info.Slice.is_volatile == false); - assert(u32_slice_info.Slice.alignment == 4); - assert(u32_slice_info.Slice.child == u32); - } + testSlice(); + comptime testSlice(); +} + +fn testSlice() void { + const u32_slice_info = @typeInfo([]u32); + assert(TypeId(u32_slice_info) == TypeId.Slice); + assert(u32_slice_info.Slice.is_const == false); + assert(u32_slice_info.Slice.is_volatile == false); + assert(u32_slice_info.Slice.alignment == 4); + assert(u32_slice_info.Slice.child == u32); } test "type info: array type info" { - comptime { - const arr_info = @typeInfo([42]bool); - assert(TypeId(arr_info) == TypeId.Array); - assert(arr_info.Array.len == 42); - assert(arr_info.Array.child == bool); - } + testArray(); + comptime testArray(); +} + +fn testArray() void { + const arr_info = @typeInfo([42]bool); + assert(TypeId(arr_info) == TypeId.Array); + assert(arr_info.Array.len == 42); + assert(arr_info.Array.child == bool); } test "type info: nullable type info" { - comptime { - const null_info = @typeInfo(?void); - assert(TypeId(null_info) == TypeId.Nullable); - assert(null_info.Nullable.child == void); - } + testNullable(); + comptime testNullable(); +} + +fn testNullable() void { + const null_info = @typeInfo(?void); + assert(TypeId(null_info) == TypeId.Nullable); + assert(null_info.Nullable.child == void); } test "type info: promise info" { - comptime { - const null_promise_info = @typeInfo(promise); - assert(TypeId(null_promise_info) == TypeId.Promise); - assert(null_promise_info.Promise.child == @typeOf(undefined)); + testPromise(); + comptime testPromise(); +} - const promise_info = @typeInfo(promise->usize); - assert(TypeId(promise_info) == TypeId.Promise); - assert(promise_info.Promise.child == usize); - } +fn testPromise() void { + const null_promise_info = @typeInfo(promise); + assert(TypeId(null_promise_info) == TypeId.Promise); + assert(null_promise_info.Promise.child == @typeOf(undefined)); + const promise_info = @typeInfo(promise->usize); + assert(TypeId(promise_info) == TypeId.Promise); + assert(promise_info.Promise.child == usize); } test "type info: error set, error union info" { - comptime { - const TestErrorSet = error { - First, - Second, - Third, - }; + testErrorSet(); + comptime testErrorSet(); +} - const error_set_info = @typeInfo(TestErrorSet); - assert(TypeId(error_set_info) == TypeId.ErrorSet); - assert(error_set_info.ErrorSet.errors.len == 3); - assert(mem.eql(u8, error_set_info.ErrorSet.errors[0].name, "First")); - assert(error_set_info.ErrorSet.errors[2].value == usize(TestErrorSet.Third)); +fn testErrorSet() void { + const TestErrorSet = error { + First, + Second, + Third, + }; - const error_union_info = @typeInfo(TestErrorSet!usize); - assert(TypeId(error_union_info) == TypeId.ErrorUnion); - assert(error_union_info.ErrorUnion.error_set == TestErrorSet); - assert(error_union_info.ErrorUnion.payload == usize); - } + const error_set_info = @typeInfo(TestErrorSet); + assert(TypeId(error_set_info) == TypeId.ErrorSet); + assert(error_set_info.ErrorSet.errors.len == 3); + assert(mem.eql(u8, error_set_info.ErrorSet.errors[0].name, "First")); + assert(error_set_info.ErrorSet.errors[2].value == usize(TestErrorSet.Third)); + + const error_union_info = @typeInfo(TestErrorSet!usize); + assert(TypeId(error_union_info) == TypeId.ErrorUnion); + assert(error_union_info.ErrorUnion.error_set == TestErrorSet); + assert(error_union_info.ErrorUnion.payload == usize); } test "type info: enum info" { - comptime { - const Os = @import("builtin").Os; + testEnum(); + comptime testEnum(); +} - const os_info = @typeInfo(Os); - assert(TypeId(os_info) == TypeId.Enum); - assert(os_info.Enum.layout == TypeInfo.ContainerLayout.Auto); - assert(os_info.Enum.fields.len == 32); - assert(mem.eql(u8, os_info.Enum.fields[1].name, "ananas")); - assert(os_info.Enum.fields[10].value == 10); - assert(os_info.Enum.tag_type == u5); - assert(os_info.Enum.defs.len == 0); - } +fn testEnum() void { + const Os = @import("builtin").Os; + + const os_info = @typeInfo(Os); + assert(TypeId(os_info) == TypeId.Enum); + assert(os_info.Enum.layout == TypeInfo.ContainerLayout.Auto); + assert(os_info.Enum.fields.len == 32); + assert(mem.eql(u8, os_info.Enum.fields[1].name, "ananas")); + assert(os_info.Enum.fields[10].value == 10); + assert(os_info.Enum.tag_type == u5); + assert(os_info.Enum.defs.len == 0); } test "type info: union info" { - comptime { - const typeinfo_info = @typeInfo(TypeInfo); - assert(TypeId(typeinfo_info) == TypeId.Union); - assert(typeinfo_info.Union.layout == TypeInfo.ContainerLayout.Auto); - assert(typeinfo_info.Union.tag_type == TypeId); - assert(typeinfo_info.Union.fields.len == 26); - assert(typeinfo_info.Union.fields[4].enum_field != null); - assert((??typeinfo_info.Union.fields[4].enum_field).value == 4); - assert(typeinfo_info.Union.fields[4].field_type == @typeOf(@typeInfo(u8).Int)); - assert(typeinfo_info.Union.defs.len == 21); + testUnion(); + comptime testUnion(); +} - const TestNoTagUnion = union { - Foo: void, - Bar: u32, - }; +fn testUnion() void { + const typeinfo_info = @typeInfo(TypeInfo); + assert(TypeId(typeinfo_info) == TypeId.Union); + assert(typeinfo_info.Union.layout == TypeInfo.ContainerLayout.Auto); + assert(typeinfo_info.Union.tag_type == TypeId); + assert(typeinfo_info.Union.fields.len == 26); + assert(typeinfo_info.Union.fields[4].enum_field != null); + assert((??typeinfo_info.Union.fields[4].enum_field).value == 4); + assert(typeinfo_info.Union.fields[4].field_type == @typeOf(@typeInfo(u8).Int)); + assert(typeinfo_info.Union.defs.len == 21); - const notag_union_info = @typeInfo(TestNoTagUnion); - assert(TypeId(notag_union_info) == TypeId.Union); - assert(notag_union_info.Union.tag_type == @typeOf(undefined)); - assert(notag_union_info.Union.layout == TypeInfo.ContainerLayout.Auto); - assert(notag_union_info.Union.fields.len == 2); - assert(notag_union_info.Union.fields[0].enum_field == null); - assert(notag_union_info.Union.fields[1].field_type == u32); + const TestNoTagUnion = union { + Foo: void, + Bar: u32, + }; - const TestExternUnion = extern union { - foo: &c_void, - }; + const notag_union_info = @typeInfo(TestNoTagUnion); + assert(TypeId(notag_union_info) == TypeId.Union); + assert(notag_union_info.Union.tag_type == @typeOf(undefined)); + assert(notag_union_info.Union.layout == TypeInfo.ContainerLayout.Auto); + assert(notag_union_info.Union.fields.len == 2); + assert(notag_union_info.Union.fields[0].enum_field == null); + assert(notag_union_info.Union.fields[1].field_type == u32); - const extern_union_info = @typeInfo(TestExternUnion); - assert(extern_union_info.Union.layout == TypeInfo.ContainerLayout.Extern); - assert(extern_union_info.Union.tag_type == @typeOf(undefined)); - assert(extern_union_info.Union.fields[0].enum_field == null); - assert(extern_union_info.Union.fields[0].field_type == &c_void); - } + const TestExternUnion = extern union { + foo: &c_void, + }; + + const extern_union_info = @typeInfo(TestExternUnion); + assert(extern_union_info.Union.layout == TypeInfo.ContainerLayout.Extern); + assert(extern_union_info.Union.tag_type == @typeOf(undefined)); + assert(extern_union_info.Union.fields[0].enum_field == null); + assert(extern_union_info.Union.fields[0].field_type == &c_void); } test "type info: struct info" { - comptime { - const struct_info = @typeInfo(TestStruct); - assert(TypeId(struct_info) == TypeId.Struct); - assert(struct_info.Struct.layout == TypeInfo.ContainerLayout.Packed); - assert(struct_info.Struct.fields.len == 3); - assert(struct_info.Struct.fields[1].offset == null); - assert(struct_info.Struct.fields[2].field_type == &TestStruct); - assert(struct_info.Struct.defs.len == 2); - assert(struct_info.Struct.defs[0].is_pub); - assert(!struct_info.Struct.defs[0].data.Fn.is_extern); - assert(struct_info.Struct.defs[0].data.Fn.lib_name == null); - assert(struct_info.Struct.defs[0].data.Fn.return_type == void); - assert(struct_info.Struct.defs[0].data.Fn.fn_type == fn(&const TestStruct)void); - } + testStruct(); + comptime testStruct(); +} + +fn testStruct() void { + const struct_info = @typeInfo(TestStruct); + assert(TypeId(struct_info) == TypeId.Struct); + assert(struct_info.Struct.layout == TypeInfo.ContainerLayout.Packed); + assert(struct_info.Struct.fields.len == 3); + assert(struct_info.Struct.fields[1].offset == null); + assert(struct_info.Struct.fields[2].field_type == &TestStruct); + assert(struct_info.Struct.defs.len == 2); + assert(struct_info.Struct.defs[0].is_pub); + assert(!struct_info.Struct.defs[0].data.Fn.is_extern); + assert(struct_info.Struct.defs[0].data.Fn.lib_name == null); + assert(struct_info.Struct.defs[0].data.Fn.return_type == void); + assert(struct_info.Struct.defs[0].data.Fn.fn_type == fn(&const TestStruct)void); } const TestStruct = packed struct { @@ -178,21 +210,24 @@ const TestStruct = packed struct { }; test "type info: function type info" { - comptime { - const fn_info = @typeInfo(@typeOf(foo)); - assert(TypeId(fn_info) == TypeId.Fn); - assert(fn_info.Fn.calling_convention == TypeInfo.CallingConvention.Unspecified); - assert(fn_info.Fn.is_generic); - assert(fn_info.Fn.args.len == 2); - assert(fn_info.Fn.is_var_args); - assert(fn_info.Fn.return_type == @typeOf(undefined)); - assert(fn_info.Fn.async_allocator_type == @typeOf(undefined)); + testFunction(); + comptime testFunction(); +} - const test_instance: TestStruct = undefined; - const bound_fn_info = @typeInfo(@typeOf(test_instance.foo)); - assert(TypeId(bound_fn_info) == TypeId.BoundFn); - assert(bound_fn_info.BoundFn.args[0].arg_type == &const TestStruct); - } +fn testFunction() void { + const fn_info = @typeInfo(@typeOf(foo)); + assert(TypeId(fn_info) == TypeId.Fn); + assert(fn_info.Fn.calling_convention == TypeInfo.CallingConvention.Unspecified); + assert(fn_info.Fn.is_generic); + assert(fn_info.Fn.args.len == 2); + assert(fn_info.Fn.is_var_args); + assert(fn_info.Fn.return_type == @typeOf(undefined)); + assert(fn_info.Fn.async_allocator_type == @typeOf(undefined)); + + const test_instance: TestStruct = undefined; + const bound_fn_info = @typeInfo(@typeOf(test_instance.foo)); + assert(TypeId(bound_fn_info) == TypeId.BoundFn); + assert(bound_fn_info.BoundFn.args[0].arg_type == &const TestStruct); } fn foo(comptime a: usize, b: bool, args: ...) usize { -- 2.54.0 From 3625df25d6fe0b11e4c1c33454b621ec8a8c10ba Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 15 May 2018 16:21:47 -0400 Subject: [PATCH 17/47] build: add flag to LLD to fix gcc 8 build (#1013) * build: add flag to LLD to fix gcc 8 build * build: add -Wno-unknown-warning-option to work around older gcc --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0aad51c7bc9d37ed652de185cfc3b4dc46cccdf2..bda576347efb87f9ebf50150efa439901982ddcc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -196,7 +196,7 @@ else() if(MSVC) set(ZIG_LLD_COMPILE_FLAGS "-std=c++11 -D_CRT_SECURE_NO_WARNINGS /w") else() - set(ZIG_LLD_COMPILE_FLAGS "-std=c++11 -fno-exceptions -fno-rtti -Wno-comment") + set(ZIG_LLD_COMPILE_FLAGS "-std=c++11 -fno-exceptions -fno-rtti -Wno-comment -Wno-class-memaccess -Wno-unknown-warning-option") endif() set_target_properties(embedded_lld_lib PROPERTIES COMPILE_FLAGS ${ZIG_LLD_COMPILE_FLAGS} -- 2.54.0 From 492a214d4c4f4feb15620dfd05230de0086825e5 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 15 May 2018 22:11:03 -0400 Subject: [PATCH 18/47] std.fmt.format: support {B} for human readable bytes --- std/fmt/index.zig | 55 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/std/fmt/index.zig b/std/fmt/index.zig index 43e758038f397f76c2b21b0cc8cc8dace754253e..e26b2f6c8bcd1dc2d9f798445a9e7681488a92fa 100644 --- a/std/fmt/index.zig +++ b/std/fmt/index.zig @@ -27,6 +27,8 @@ pub fn format(context: var, comptime Errors: type, output: fn(@typeOf(context), Character, Buf, BufWidth, + Bytes, + BytesWidth, }; comptime var start_index = 0; @@ -95,6 +97,10 @@ pub fn format(context: var, comptime Errors: type, output: fn(@typeOf(context), '.' => { state = State.Float; }, + 'B' => { + width = 0; + state = State.Bytes; + }, else => @compileError("Unknown format character: " ++ []u8{c}), }, State.Buf => switch (c) { @@ -206,6 +212,30 @@ pub fn format(context: var, comptime Errors: type, output: fn(@typeOf(context), }, else => @compileError("Unexpected character in format string: " ++ []u8{c}), }, + State.Bytes => switch (c) { + '}' => { + try formatBytes(args[next_arg], 0, context, Errors, output); + next_arg += 1; + state = State.Start; + start_index = i + 1; + }, + '0' ... '9' => { + width_start = i; + state = State.BytesWidth; + }, + else => @compileError("Unexpected character in format string: " ++ []u8{c}), + }, + State.BytesWidth => switch (c) { + '}' => { + width = comptime (parseUnsigned(usize, fmt[width_start..i], 10) catch unreachable); + try formatBytes(args[next_arg], width, context, Errors, output); + next_arg += 1; + state = State.Start; + start_index = i + 1; + }, + '0' ... '9' => {}, + else => @compileError("Unexpected character in format string: " ++ []u8{c}), + }, } } comptime { @@ -520,6 +550,25 @@ pub fn formatFloatDecimal(value: var, maybe_precision: ?usize, context: var, com } } +pub fn formatBytes(value: var, width: ?usize, + context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8)Errors!void) Errors!void +{ + if (value == 0) { + return output(context, "0B"); + } + + const mags = " KMGTPEZY"; + const magnitude = math.min(math.log2(value) / 10, mags.len - 1); + const new_value = f64(value) / math.pow(f64, 1024, f64(magnitude)); + const suffix = mags[magnitude]; + + try formatFloatDecimal(new_value, width, context, Errors, output); + + if (suffix != ' ') { + try output(context, (&suffix)[0..1]); + } + return output(context, "B"); +} pub fn formatInt(value: var, base: u8, uppercase: bool, width: usize, context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8)Errors!void) Errors!void @@ -767,6 +816,12 @@ test "fmt.format" { const result = try bufPrint(buf1[0..], "u3: {}\n", value); assert(mem.eql(u8, result, "u3: 5\n")); } + { + var buf1: [32]u8 = undefined; + const value: usize = 63 * 1024 * 1024; + const result = try bufPrint(buf1[0..], "file size: {B}\n", value); + assert(mem.eql(u8, result, "file size: 63MB\n")); + } { // Dummy field because of https://github.com/zig-lang/zig/issues/557. const Struct = struct { -- 2.54.0 From ee5f9ffad02b3cf263c13ca58c4d2e4526e29a84 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 16 May 2018 00:27:18 -0400 Subject: [PATCH 19/47] zig fmt: add comma on last switch prong --- std/zig/parse.zig | 2 +- std/zig/parser_test.zig | 31 +++++++++++++++++++++++++++++++ std/zig/render.zig | 15 ++++++++++++++- 3 files changed, 46 insertions(+), 2 deletions(-) diff --git a/std/zig/parse.zig b/std/zig/parse.zig index f2376f0df310261df14f7b1579a5281f2996f7b0..4f1e3dcefeb40e71dc68ee5aeedc824b4e458a6d 100644 --- a/std/zig/parse.zig +++ b/std/zig/parse.zig @@ -1406,7 +1406,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { }, State.SwitchCaseCommaOrEnd => |list_state| { - switch (expectCommaOrEnd(&tok_it, &tree, Token.Id.RParen)) { + switch (expectCommaOrEnd(&tok_it, &tree, Token.Id.RBrace)) { ExpectCommaOrEndResult.end_token => |maybe_end| if (maybe_end) |end| { *list_state.ptr = end; continue; diff --git a/std/zig/parser_test.zig b/std/zig/parser_test.zig index f95ecfaee357b83c6aca08cebc14bbdeb7e073b1..129e62e6dda8bc1078f8925edceb98a6e67bfa40 100644 --- a/std/zig/parser_test.zig +++ b/std/zig/parser_test.zig @@ -1,3 +1,34 @@ +test "zig fmt: add comma on last switch prong" { + try testTransform( + \\test "aoeu" { + \\switch (self.init_arg_expr) { + \\ InitArg.Type => |t| { }, + \\ InitArg.None, + \\ InitArg.Enum => { } + \\} + \\ switch (self.init_arg_expr) { + \\ InitArg.Type => |t| { }, + \\ InitArg.None, + \\ InitArg.Enum => { }//line comment + \\ } + \\} + , + \\test "aoeu" { + \\ switch (self.init_arg_expr) { + \\ InitArg.Type => |t| {}, + \\ InitArg.None, + \\ InitArg.Enum => {}, + \\ } + \\ switch (self.init_arg_expr) { + \\ InitArg.Type => |t| {}, + \\ InitArg.None, + \\ InitArg.Enum => {}, //line comment + \\ } + \\} + \\ + ); +} + test "zig fmt: same-line doc comment on variable declaration" { try testTransform( \\pub const MAP_ANONYMOUS = 0x1000; /// allocated from memory, swap space diff --git a/std/zig/render.zig b/std/zig/render.zig index 13ef4607f49e28028749f984a68c76215b140d54..5084c1d096d78ca6a7e45fd7ba2706b975481d19 100644 --- a/std/zig/render.zig +++ b/std/zig/render.zig @@ -831,7 +831,20 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind } try renderExpression(allocator, stream, tree, indent, switch_case.expr); - try renderToken(tree, stream, switch_case.lastToken() + 1, indent, true); + { + // Handle missing comma after last switch case + var index = switch_case.lastToken() + 1; + switch (tree.tokens.at(index).id) { + Token.Id.RBrace => { + try stream.write(","); + }, + Token.Id.LineComment => { + try stream.write(", "); + try renderToken(tree, stream, index, indent, true); + }, + else => try renderToken(tree, stream, index, indent, true), + } + } }, ast.Node.Id.SwitchElse => { const switch_else = @fieldParentPtr(ast.Node.SwitchElse, "base", base); -- 2.54.0 From 288fc3a8d361972daeded19d207b410128d70d67 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 16 May 2018 00:43:28 -0400 Subject: [PATCH 20/47] convert more std lib files to postfix pointer deref --- std/crypto/test.zig | 3 +- std/fmt/errol/index.zig | 54 +- std/os/darwin.zig | 274 +++-- std/zig/ast.zig | 71 +- std/zig/parse.zig | 2083 +++++++++++++++++---------------------- std/zig/render.zig | 88 +- 6 files changed, 1203 insertions(+), 1370 deletions(-) diff --git a/std/crypto/test.zig b/std/crypto/test.zig index e41c6a7a2d502cc3e7f5907a7f430161df951d91..3fa24272e5ecdc49b9b346e911f46f94b9b78395 100644 --- a/std/crypto/test.zig +++ b/std/crypto/test.zig @@ -14,9 +14,8 @@ pub fn assertEqualHash(comptime Hasher: var, comptime expected: []const u8, inpu pub fn assertEqual(comptime expected: []const u8, input: []const u8) void { var expected_bytes: [expected.len / 2]u8 = undefined; for (expected_bytes) |*r, i| { - *r = fmt.parseInt(u8, expected[2*i .. 2*i+2], 16) catch unreachable; + r.* = fmt.parseInt(u8, expected[2 * i .. 2 * i + 2], 16) catch unreachable; } debug.assert(mem.eql(u8, expected_bytes, input)); } - diff --git a/std/fmt/errol/index.zig b/std/fmt/errol/index.zig index 00c69cd2948397ca1c2e3f54f288abfdbe6e1d9a..f4ec251b77916887f96cae2648018fd4bc57118e 100644 --- a/std/fmt/errol/index.zig +++ b/std/fmt/errol/index.zig @@ -86,7 +86,7 @@ pub fn errol3(value: f64, buffer: []u8) FloatDecimal { const data = enum3_data[i]; const digits = buffer[1..data.str.len + 1]; mem.copy(u8, digits, data.str); - return FloatDecimal { + return FloatDecimal{ .digits = digits, .exp = data.exp, }; @@ -105,7 +105,6 @@ fn errol3u(val: f64, buffer: []u8) FloatDecimal { return errolFixed(val, buffer); } - // normalize the midpoint const e = math.frexp(val).exponent; @@ -137,11 +136,11 @@ fn errol3u(val: f64, buffer: []u8) FloatDecimal { } // compute boundaries - var high = HP { + var high = HP{ .val = mid.val, .off = mid.off + (fpnext(val) - val) * lten * ten / 2.0, }; - var low = HP { + var low = HP{ .val = mid.val, .off = mid.off + (fpprev(val) - val) * lten * ten / 2.0, }; @@ -171,15 +170,12 @@ fn errol3u(val: f64, buffer: []u8) FloatDecimal { var buf_index: usize = 1; while (true) { var hdig = u8(math.floor(high.val)); - if ((high.val == f64(hdig)) and (high.off < 0)) - hdig -= 1; + if ((high.val == f64(hdig)) and (high.off < 0)) hdig -= 1; var ldig = u8(math.floor(low.val)); - if ((low.val == f64(ldig)) and (low.off < 0)) - ldig -= 1; + if ((low.val == f64(ldig)) and (low.off < 0)) ldig -= 1; - if (ldig != hdig) - break; + if (ldig != hdig) break; buffer[buf_index] = hdig + '0'; buf_index += 1; @@ -191,13 +187,12 @@ fn errol3u(val: f64, buffer: []u8) FloatDecimal { const tmp = (high.val + low.val) / 2.0; var mdig = u8(math.floor(tmp + 0.5)); - if ((f64(mdig) - tmp) == 0.5 and (mdig & 0x1) != 0) - mdig -= 1; + if ((f64(mdig) - tmp) == 0.5 and (mdig & 0x1) != 0) mdig -= 1; buffer[buf_index] = mdig + '0'; buf_index += 1; - return FloatDecimal { + return FloatDecimal{ .digits = buffer[1..buf_index], .exp = exp, }; @@ -235,7 +230,7 @@ fn hpProd(in: &const HP, val: f64) HP { const p = in.val * val; const e = ((hi * hi2 - p) + lo * hi2 + hi * lo2) + lo * lo2; - return HP { + return HP{ .val = p, .off = in.off * val + e, }; @@ -246,8 +241,8 @@ fn hpProd(in: &const HP, val: f64) HP { /// @hi: The high bits. /// @lo: The low bits. fn split(val: f64, hi: &f64, lo: &f64) void { - *hi = gethi(val); - *lo = val - *hi; + hi.* = gethi(val); + lo.* = val - hi.*; } fn gethi(in: f64) f64 { @@ -301,7 +296,6 @@ fn hpMul10(hp: &HP) void { hpNormalize(hp); } - /// Integer conversion algorithm, guaranteed correct, optimal, and best. /// @val: The val. /// @buf: The output buffer. @@ -343,8 +337,7 @@ fn errolInt(val: f64, buffer: []u8) FloatDecimal { } const m64 = @truncate(u64, @divTrunc(mid, x)); - if (lf != hf) - mi += 19; + if (lf != hf) mi += 19; var buf_index = u64toa(m64, buffer) - 1; @@ -354,7 +347,7 @@ fn errolInt(val: f64, buffer: []u8) FloatDecimal { buf_index += 1; } - return FloatDecimal { + return FloatDecimal{ .digits = buffer[0..buf_index], .exp = i32(buf_index) + mi, }; @@ -396,25 +389,24 @@ fn errolFixed(val: f64, buffer: []u8) FloatDecimal { buffer[j] = u8(mdig + '0'); j += 1; - if(hdig != ldig or j > 50) - break; + if (hdig != ldig or j > 50) break; } if (mid > 0.5) { - buffer[j-1] += 1; - } else if ((mid == 0.5) and (buffer[j-1] & 0x1) != 0) { - buffer[j-1] += 1; + buffer[j - 1] += 1; + } else if ((mid == 0.5) and (buffer[j - 1] & 0x1) != 0) { + buffer[j - 1] += 1; } } else { - while (buffer[j-1] == '0') { - buffer[j-1] = 0; + while (buffer[j - 1] == '0') { + buffer[j - 1] = 0; j -= 1; } } buffer[j] = 0; - return FloatDecimal { + return FloatDecimal{ .digits = buffer[0..j], .exp = exp, }; @@ -587,7 +579,7 @@ fn u64toa(value_param: u64, buffer: []u8) usize { buffer[buf_index] = c_digits_lut[d8 + 1]; buf_index += 1; } else { - const a = u32(value / kTen16); // 1 to 1844 + const a = u32(value / kTen16); // 1 to 1844 value %= kTen16; if (a < 10) { @@ -686,7 +678,6 @@ fn fpeint(from: f64) u128 { return u128(1) << @truncate(u7, (bits >> 52) -% 1023); } - /// Given two different integers with the same length in terms of the number /// of decimal digits, index the digits from the right-most position starting /// from zero, find the first index where the digits in the two integers @@ -713,7 +704,6 @@ fn mismatch10(a: u64, b: u64) i32 { a_copy /= 10; b_copy /= 10; - if (a_copy == b_copy) - return i; + if (a_copy == b_copy) return i; } } diff --git a/std/os/darwin.zig b/std/os/darwin.zig index 0a62b03ab28c450fd6b351003447403a3e229e0b..45359e757dff98c4390cdcce3b8ddab5daf38757 100644 --- a/std/os/darwin.zig +++ b/std/os/darwin.zig @@ -10,33 +10,56 @@ pub const STDIN_FILENO = 0; pub const STDOUT_FILENO = 1; pub const STDERR_FILENO = 2; -pub const PROT_NONE = 0x00; /// [MC2] no permissions -pub const PROT_READ = 0x01; /// [MC2] pages can be read -pub const PROT_WRITE = 0x02; /// [MC2] pages can be written -pub const PROT_EXEC = 0x04; /// [MC2] pages can be executed +/// [MC2] no permissions +pub const PROT_NONE = 0x00; +/// [MC2] pages can be read +pub const PROT_READ = 0x01; +/// [MC2] pages can be written +pub const PROT_WRITE = 0x02; +/// [MC2] pages can be executed +pub const PROT_EXEC = 0x04; -pub const MAP_ANONYMOUS = 0x1000; /// allocated from memory, swap space -pub const MAP_FILE = 0x0000; /// map from file (default) -pub const MAP_FIXED = 0x0010; /// interpret addr exactly -pub const MAP_HASSEMAPHORE = 0x0200; /// region may contain semaphores -pub const MAP_PRIVATE = 0x0002; /// changes are private -pub const MAP_SHARED = 0x0001; /// share changes -pub const MAP_NOCACHE = 0x0400; /// don't cache pages for this mapping -pub const MAP_NORESERVE = 0x0040; /// don't reserve needed swap area +/// allocated from memory, swap space +pub const MAP_ANONYMOUS = 0x1000; +/// map from file (default) +pub const MAP_FILE = 0x0000; +/// interpret addr exactly +pub const MAP_FIXED = 0x0010; +/// region may contain semaphores +pub const MAP_HASSEMAPHORE = 0x0200; +/// changes are private +pub const MAP_PRIVATE = 0x0002; +/// share changes +pub const MAP_SHARED = 0x0001; +/// don't cache pages for this mapping +pub const MAP_NOCACHE = 0x0400; +/// don't reserve needed swap area +pub const MAP_NORESERVE = 0x0040; pub const MAP_FAILED = @maxValue(usize); -pub const WNOHANG = 0x00000001; /// [XSI] no hang in wait/no child to reap -pub const WUNTRACED = 0x00000002; /// [XSI] notify on stop, untraced child +/// [XSI] no hang in wait/no child to reap +pub const WNOHANG = 0x00000001; +/// [XSI] notify on stop, untraced child +pub const WUNTRACED = 0x00000002; -pub const SA_ONSTACK = 0x0001; /// take signal on signal stack -pub const SA_RESTART = 0x0002; /// restart system on signal return -pub const SA_RESETHAND = 0x0004; /// reset to SIG_DFL when taking signal -pub const SA_NOCLDSTOP = 0x0008; /// do not generate SIGCHLD on child stop -pub const SA_NODEFER = 0x0010; /// don't mask the signal we're delivering -pub const SA_NOCLDWAIT = 0x0020; /// don't keep zombies around -pub const SA_SIGINFO = 0x0040; /// signal handler with SA_SIGINFO args -pub const SA_USERTRAMP = 0x0100; /// do not bounce off kernel's sigtramp -pub const SA_64REGSET = 0x0200; /// signal handler with SA_SIGINFO args with 64bit regs information +/// take signal on signal stack +pub const SA_ONSTACK = 0x0001; +/// restart system on signal return +pub const SA_RESTART = 0x0002; +/// reset to SIG_DFL when taking signal +pub const SA_RESETHAND = 0x0004; +/// do not generate SIGCHLD on child stop +pub const SA_NOCLDSTOP = 0x0008; +/// don't mask the signal we're delivering +pub const SA_NODEFER = 0x0010; +/// don't keep zombies around +pub const SA_NOCLDWAIT = 0x0020; +/// signal handler with SA_SIGINFO args +pub const SA_SIGINFO = 0x0040; +/// do not bounce off kernel's sigtramp +pub const SA_USERTRAMP = 0x0100; +/// signal handler with SA_SIGINFO args with 64bit regs information +pub const SA_64REGSET = 0x0200; pub const O_LARGEFILE = 0x0000; pub const O_PATH = 0x0000; @@ -46,20 +69,34 @@ pub const X_OK = 1; pub const W_OK = 2; pub const R_OK = 4; -pub const O_RDONLY = 0x0000; /// open for reading only -pub const O_WRONLY = 0x0001; /// open for writing only -pub const O_RDWR = 0x0002; /// open for reading and writing -pub const O_NONBLOCK = 0x0004; /// do not block on open or for data to become available -pub const O_APPEND = 0x0008; /// append on each write -pub const O_CREAT = 0x0200; /// create file if it does not exist -pub const O_TRUNC = 0x0400; /// truncate size to 0 -pub const O_EXCL = 0x0800; /// error if O_CREAT and the file exists -pub const O_SHLOCK = 0x0010; /// atomically obtain a shared lock -pub const O_EXLOCK = 0x0020; /// atomically obtain an exclusive lock -pub const O_NOFOLLOW = 0x0100; /// do not follow symlinks -pub const O_SYMLINK = 0x200000; /// allow open of symlinks -pub const O_EVTONLY = 0x8000; /// descriptor requested for event notifications only -pub const O_CLOEXEC = 0x1000000; /// mark as close-on-exec +/// open for reading only +pub const O_RDONLY = 0x0000; +/// open for writing only +pub const O_WRONLY = 0x0001; +/// open for reading and writing +pub const O_RDWR = 0x0002; +/// do not block on open or for data to become available +pub const O_NONBLOCK = 0x0004; +/// append on each write +pub const O_APPEND = 0x0008; +/// create file if it does not exist +pub const O_CREAT = 0x0200; +/// truncate size to 0 +pub const O_TRUNC = 0x0400; +/// error if O_CREAT and the file exists +pub const O_EXCL = 0x0800; +/// atomically obtain a shared lock +pub const O_SHLOCK = 0x0010; +/// atomically obtain an exclusive lock +pub const O_EXLOCK = 0x0020; +/// do not follow symlinks +pub const O_NOFOLLOW = 0x0100; +/// allow open of symlinks +pub const O_SYMLINK = 0x200000; +/// descriptor requested for event notifications only +pub const O_EVTONLY = 0x8000; +/// mark as close-on-exec +pub const O_CLOEXEC = 0x1000000; pub const O_ACCMODE = 3; pub const O_ALERT = 536870912; @@ -87,52 +124,102 @@ pub const DT_LNK = 10; pub const DT_SOCK = 12; pub const DT_WHT = 14; -pub const SIG_BLOCK = 1; /// block specified signal set -pub const SIG_UNBLOCK = 2; /// unblock specified signal set -pub const SIG_SETMASK = 3; /// set specified signal set +/// block specified signal set +pub const SIG_BLOCK = 1; +/// unblock specified signal set +pub const SIG_UNBLOCK = 2; +/// set specified signal set +pub const SIG_SETMASK = 3; -pub const SIGHUP = 1; /// hangup -pub const SIGINT = 2; /// interrupt -pub const SIGQUIT = 3; /// quit -pub const SIGILL = 4; /// illegal instruction (not reset when caught) -pub const SIGTRAP = 5; /// trace trap (not reset when caught) -pub const SIGABRT = 6; /// abort() -pub const SIGPOLL = 7; /// pollable event ([XSR] generated, not supported) -pub const SIGIOT = SIGABRT; /// compatibility -pub const SIGEMT = 7; /// EMT instruction -pub const SIGFPE = 8; /// floating point exception -pub const SIGKILL = 9; /// kill (cannot be caught or ignored) -pub const SIGBUS = 10; /// bus error -pub const SIGSEGV = 11; /// segmentation violation -pub const SIGSYS = 12; /// bad argument to system call -pub const SIGPIPE = 13; /// write on a pipe with no one to read it -pub const SIGALRM = 14; /// alarm clock -pub const SIGTERM = 15; /// software termination signal from kill -pub const SIGURG = 16; /// urgent condition on IO channel -pub const SIGSTOP = 17; /// sendable stop signal not from tty -pub const SIGTSTP = 18; /// stop signal from tty -pub const SIGCONT = 19; /// continue a stopped process -pub const SIGCHLD = 20; /// to parent on child stop or exit -pub const SIGTTIN = 21; /// to readers pgrp upon background tty read -pub const SIGTTOU = 22; /// like TTIN for output if (tp->t_local<OSTOP) -pub const SIGIO = 23; /// input/output possible signal -pub const SIGXCPU = 24; /// exceeded CPU time limit -pub const SIGXFSZ = 25; /// exceeded file size limit -pub const SIGVTALRM = 26; /// virtual time alarm -pub const SIGPROF = 27; /// profiling time alarm -pub const SIGWINCH = 28; /// window size changes -pub const SIGINFO = 29; /// information request -pub const SIGUSR1 = 30; /// user defined signal 1 -pub const SIGUSR2 = 31; /// user defined signal 2 +/// hangup +pub const SIGHUP = 1; +/// interrupt +pub const SIGINT = 2; +/// quit +pub const SIGQUIT = 3; +/// illegal instruction (not reset when caught) +pub const SIGILL = 4; +/// trace trap (not reset when caught) +pub const SIGTRAP = 5; +/// abort() +pub const SIGABRT = 6; +/// pollable event ([XSR] generated, not supported) +pub const SIGPOLL = 7; +/// compatibility +pub const SIGIOT = SIGABRT; +/// EMT instruction +pub const SIGEMT = 7; +/// floating point exception +pub const SIGFPE = 8; +/// kill (cannot be caught or ignored) +pub const SIGKILL = 9; +/// bus error +pub const SIGBUS = 10; +/// segmentation violation +pub const SIGSEGV = 11; +/// bad argument to system call +pub const SIGSYS = 12; +/// write on a pipe with no one to read it +pub const SIGPIPE = 13; +/// alarm clock +pub const SIGALRM = 14; +/// software termination signal from kill +pub const SIGTERM = 15; +/// urgent condition on IO channel +pub const SIGURG = 16; +/// sendable stop signal not from tty +pub const SIGSTOP = 17; +/// stop signal from tty +pub const SIGTSTP = 18; +/// continue a stopped process +pub const SIGCONT = 19; +/// to parent on child stop or exit +pub const SIGCHLD = 20; +/// to readers pgrp upon background tty read +pub const SIGTTIN = 21; +/// like TTIN for output if (tp->t_local<OSTOP) +pub const SIGTTOU = 22; +/// input/output possible signal +pub const SIGIO = 23; +/// exceeded CPU time limit +pub const SIGXCPU = 24; +/// exceeded file size limit +pub const SIGXFSZ = 25; +/// virtual time alarm +pub const SIGVTALRM = 26; +/// profiling time alarm +pub const SIGPROF = 27; +/// window size changes +pub const SIGWINCH = 28; +/// information request +pub const SIGINFO = 29; +/// user defined signal 1 +pub const SIGUSR1 = 30; +/// user defined signal 2 +pub const SIGUSR2 = 31; -fn wstatus(x: i32) i32 { return x & 0o177; } +fn wstatus(x: i32) i32 { + return x & 0o177; +} const wstopped = 0o177; -pub fn WEXITSTATUS(x: i32) i32 { return x >> 8; } -pub fn WTERMSIG(x: i32) i32 { return wstatus(x); } -pub fn WSTOPSIG(x: i32) i32 { return x >> 8; } -pub fn WIFEXITED(x: i32) bool { return wstatus(x) == 0; } -pub fn WIFSTOPPED(x: i32) bool { return wstatus(x) == wstopped and WSTOPSIG(x) != 0x13; } -pub fn WIFSIGNALED(x: i32) bool { return wstatus(x) != wstopped and wstatus(x) != 0; } +pub fn WEXITSTATUS(x: i32) i32 { + return x >> 8; +} +pub fn WTERMSIG(x: i32) i32 { + return wstatus(x); +} +pub fn WSTOPSIG(x: i32) i32 { + return x >> 8; +} +pub fn WIFEXITED(x: i32) bool { + return wstatus(x) == 0; +} +pub fn WIFSTOPPED(x: i32) bool { + return wstatus(x) == wstopped and WSTOPSIG(x) != 0x13; +} +pub fn WIFSIGNALED(x: i32) bool { + return wstatus(x) != wstopped and wstatus(x) != 0; +} /// Get the errno from a syscall return value, or 0 for no error. pub fn getErrno(r: usize) usize { @@ -184,11 +271,8 @@ pub fn write(fd: i32, buf: &const u8, nbyte: usize) usize { return errnoWrap(c.write(fd, @ptrCast(&const c_void, buf), nbyte)); } -pub fn mmap(address: ?&u8, length: usize, prot: usize, flags: u32, fd: i32, - offset: isize) usize -{ - const ptr_result = c.mmap(@ptrCast(&c_void, address), length, - @bitCast(c_int, c_uint(prot)), @bitCast(c_int, c_uint(flags)), fd, offset); +pub fn mmap(address: ?&u8, length: usize, prot: usize, flags: u32, fd: i32, offset: isize) usize { + const ptr_result = c.mmap(@ptrCast(&c_void, address), length, @bitCast(c_int, c_uint(prot)), @bitCast(c_int, c_uint(flags)), fd, offset); const isize_result = @bitCast(isize, @ptrToInt(ptr_result)); return errnoWrap(isize_result); } @@ -202,7 +286,7 @@ pub fn unlink(path: &const u8) usize { } pub fn getcwd(buf: &u8, size: usize) usize { - return if (c.getcwd(buf, size) == null) @bitCast(usize, -isize(*c._errno())) else 0; + return if (c.getcwd(buf, size) == null) @bitCast(usize, -isize(c._errno().*)) else 0; } pub fn waitpid(pid: i32, status: &i32, options: u32) usize { @@ -223,7 +307,6 @@ pub fn pipe(fds: &[2]i32) usize { return errnoWrap(c.pipe(@ptrCast(&c_int, fds))); } - pub fn getdirentries64(fd: i32, buf_ptr: &u8, buf_len: usize, basep: &i64) usize { return errnoWrap(@bitCast(isize, c.__getdirentries64(fd, buf_ptr, buf_len, basep))); } @@ -269,7 +352,7 @@ pub fn nanosleep(req: &const timespec, rem: ?×pec) usize { } pub fn realpath(noalias filename: &const u8, noalias resolved_name: &u8) usize { - return if (c.realpath(filename, resolved_name) == null) @bitCast(usize, -isize(*c._errno())) else 0; + return if (c.realpath(filename, resolved_name) == null) @bitCast(usize, -isize(c._errno().*)) else 0; } pub fn setreuid(ruid: u32, euid: u32) usize { @@ -287,8 +370,8 @@ pub fn sigprocmask(flags: u32, noalias set: &const sigset_t, noalias oldset: ?&s pub fn sigaction(sig: u5, noalias act: &const Sigaction, noalias oact: ?&Sigaction) usize { assert(sig != SIGKILL); assert(sig != SIGSTOP); - var cact = c.Sigaction { - .handler = @ptrCast(extern fn(c_int)void, act.handler), + var cact = c.Sigaction{ + .handler = @ptrCast(extern fn(c_int) void, act.handler), .sa_flags = @bitCast(c_int, act.flags), .sa_mask = act.mask, }; @@ -298,8 +381,8 @@ pub fn sigaction(sig: u5, noalias act: &const Sigaction, noalias oact: ?&Sigacti return result; } if (oact) |old| { - *old = Sigaction { - .handler = @ptrCast(extern fn(i32)void, coact.handler), + old.* = Sigaction{ + .handler = @ptrCast(extern fn(i32) void, coact.handler), .flags = @bitCast(u32, coact.sa_flags), .mask = coact.sa_mask, }; @@ -319,23 +402,22 @@ pub const sockaddr = c.sockaddr; /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. pub const Sigaction = struct { - handler: extern fn(i32)void, + handler: extern fn(i32) void, mask: sigset_t, flags: u32, }; pub fn sigaddset(set: &sigset_t, signo: u5) void { - *set |= u32(1) << (signo - 1); + set.* |= u32(1) << (signo - 1); } /// Takes the return value from a syscall and formats it back in the way /// that the kernel represents it to libc. Errno was a mistake, let's make /// it go away forever. fn errnoWrap(value: isize) usize { - return @bitCast(usize, if (value == -1) -isize(*c._errno()) else value); + return @bitCast(usize, if (value == -1) -isize(c._errno().*) else value); } - pub const timezone = c.timezone; pub const timeval = c.timeval; pub const mach_timebase_info_data = c.mach_timebase_info_data; diff --git a/std/zig/ast.zig b/std/zig/ast.zig index 596b57bdb6fbe6646604ae266c29cdd03bc9a28f..86135fe1009e8f67358e3fd3fedb94f5b085b05b 100644 --- a/std/zig/ast.zig +++ b/std/zig/ast.zig @@ -40,7 +40,7 @@ pub const Tree = struct { }; pub fn tokenLocationPtr(self: &Tree, start_index: usize, token: &const Token) Location { - var loc = Location { + var loc = Location{ .line = 0, .column = 0, .line_start = start_index, @@ -71,7 +71,6 @@ pub const Tree = struct { pub fn dump(self: &Tree) void { self.root_node.base.dump(0); } - }; pub const Error = union(enum) { @@ -95,7 +94,7 @@ pub const Error = union(enum) { ExpectedCommaOrEnd: ExpectedCommaOrEnd, pub fn render(self: &Error, tokens: &Tree.TokenList, stream: var) !void { - switch (*self) { + switch (self.*) { // TODO https://github.com/zig-lang/zig/issues/683 @TagType(Error).InvalidToken => |*x| return x.render(tokens, stream), @TagType(Error).ExpectedVarDeclOrFn => |*x| return x.render(tokens, stream), @@ -119,7 +118,7 @@ pub const Error = union(enum) { } pub fn loc(self: &Error) TokenIndex { - switch (*self) { + switch (self.*) { // TODO https://github.com/zig-lang/zig/issues/683 @TagType(Error).InvalidToken => |x| return x.token, @TagType(Error).ExpectedVarDeclOrFn => |x| return x.token, @@ -144,15 +143,12 @@ pub const Error = union(enum) { pub const InvalidToken = SingleTokenError("Invalid token {}"); pub const ExpectedVarDeclOrFn = SingleTokenError("Expected variable declaration or function, found {}"); - pub const ExpectedAggregateKw = SingleTokenError("Expected " ++ - @tagName(Token.Id.Keyword_struct) ++ ", " ++ @tagName(Token.Id.Keyword_union) ++ ", or " ++ - @tagName(Token.Id.Keyword_enum) ++ ", found {}"); + pub const ExpectedAggregateKw = SingleTokenError("Expected " ++ @tagName(Token.Id.Keyword_struct) ++ ", " ++ @tagName(Token.Id.Keyword_union) ++ ", or " ++ @tagName(Token.Id.Keyword_enum) ++ ", found {}"); pub const ExpectedEqOrSemi = SingleTokenError("Expected '=' or ';', found {}"); pub const ExpectedSemiOrLBrace = SingleTokenError("Expected ';' or '{{', found {}"); pub const ExpectedLabelable = SingleTokenError("Expected 'while', 'for', 'inline', 'suspend', or '{{', found {}"); pub const ExpectedInlinable = SingleTokenError("Expected 'while' or 'for', found {}"); - pub const ExpectedAsmOutputReturnOrType = SingleTokenError("Expected '->' or " ++ - @tagName(Token.Id.Identifier) ++ ", found {}"); + pub const ExpectedAsmOutputReturnOrType = SingleTokenError("Expected '->' or " ++ @tagName(Token.Id.Identifier) ++ ", found {}"); pub const ExpectedSliceOrRBracket = SingleTokenError("Expected ']' or '..', found {}"); pub const ExpectedPrimaryExpr = SingleTokenError("Expected primary expression, found {}"); @@ -165,8 +161,7 @@ pub const Error = union(enum) { node: &Node, pub fn render(self: &ExpectedCall, tokens: &Tree.TokenList, stream: var) !void { - return stream.print("expected " ++ @tagName(@TagType(Node.SuffixOp.Op).Call) ++ ", found {}", - @tagName(self.node.id)); + return stream.print("expected " ++ @tagName(@TagType(Node.SuffixOp.Op).Call) ++ ", found {}", @tagName(self.node.id)); } }; @@ -174,8 +169,7 @@ pub const Error = union(enum) { node: &Node, pub fn render(self: &ExpectedCallOrFnProto, tokens: &Tree.TokenList, stream: var) !void { - return stream.print("expected " ++ @tagName(@TagType(Node.SuffixOp.Op).Call) ++ " or " ++ - @tagName(Node.Id.FnProto) ++ ", found {}", @tagName(self.node.id)); + return stream.print("expected " ++ @tagName(@TagType(Node.SuffixOp.Op).Call) ++ " or " ++ @tagName(Node.Id.FnProto) ++ ", found {}", @tagName(self.node.id)); } }; @@ -445,17 +439,17 @@ pub const Node = struct { pub fn iterate(self: &Root, index: usize) ?&Node { if (index < self.decls.len) { - return *self.decls.at(index); + return self.decls.at(index).*; } return null; } pub fn firstToken(self: &Root) TokenIndex { - return if (self.decls.len == 0) self.eof_token else (*self.decls.at(0)).firstToken(); + return if (self.decls.len == 0) self.eof_token else (self.decls.at(0).*).firstToken(); } pub fn lastToken(self: &Root) TokenIndex { - return if (self.decls.len == 0) self.eof_token else (*self.decls.at(self.decls.len - 1)).lastToken(); + return if (self.decls.len == 0) self.eof_token else (self.decls.at(self.decls.len - 1).*).lastToken(); } }; @@ -545,7 +539,7 @@ pub const Node = struct { pub fn iterate(self: &ErrorSetDecl, index: usize) ?&Node { var i = index; - if (i < self.decls.len) return *self.decls.at(i); + if (i < self.decls.len) return self.decls.at(i).*; i -= self.decls.len; return null; @@ -598,10 +592,10 @@ pub const Node = struct { i -= 1; }, InitArg.None, - InitArg.Enum => { } + InitArg.Enum => {}, } - if (i < self.fields_and_decls.len) return *self.fields_and_decls.at(i); + if (i < self.fields_and_decls.len) return self.fields_and_decls.at(i).*; i -= self.fields_and_decls.len; return null; @@ -814,7 +808,7 @@ pub const Node = struct { i -= 1; } - if (i < self.params.len) return *self.params.at(self.params.len - i - 1); + if (i < self.params.len) return self.params.at(self.params.len - i - 1).*; i -= self.params.len; if (self.align_expr) |align_expr| { @@ -839,7 +833,6 @@ pub const Node = struct { i -= 1; } - return null; } @@ -934,7 +927,7 @@ pub const Node = struct { pub fn iterate(self: &Block, index: usize) ?&Node { var i = index; - if (i < self.statements.len) return *self.statements.at(i); + if (i < self.statements.len) return self.statements.at(i).*; i -= self.statements.len; return null; @@ -1119,6 +1112,7 @@ pub const Node = struct { base: Node, switch_token: TokenIndex, expr: &Node, + /// these can be SwitchCase nodes or LineComment nodes cases: CaseList, rbrace: TokenIndex, @@ -1131,7 +1125,7 @@ pub const Node = struct { if (i < 1) return self.expr; i -= 1; - if (i < self.cases.len) return *self.cases.at(i); + if (i < self.cases.len) return self.cases.at(i).*; i -= self.cases.len; return null; @@ -1157,7 +1151,7 @@ pub const Node = struct { pub fn iterate(self: &SwitchCase, index: usize) ?&Node { var i = index; - if (i < self.items.len) return *self.items.at(i); + if (i < self.items.len) return self.items.at(i).*; i -= self.items.len; if (self.payload) |payload| { @@ -1172,7 +1166,7 @@ pub const Node = struct { } pub fn firstToken(self: &SwitchCase) TokenIndex { - return (*self.items.at(0)).firstToken(); + return (self.items.at(0).*).firstToken(); } pub fn lastToken(self: &SwitchCase) TokenIndex { @@ -1616,7 +1610,7 @@ pub const Node = struct { switch (self.op) { @TagType(Op).Call => |*call_info| { - if (i < call_info.params.len) return *call_info.params.at(i); + if (i < call_info.params.len) return call_info.params.at(i).*; i -= call_info.params.len; }, Op.ArrayAccess => |index_expr| { @@ -1633,11 +1627,11 @@ pub const Node = struct { } }, Op.ArrayInitializer => |*exprs| { - if (i < exprs.len) return *exprs.at(i); + if (i < exprs.len) return exprs.at(i).*; i -= exprs.len; }, Op.StructInitializer => |*fields| { - if (i < fields.len) return *fields.at(i); + if (i < fields.len) return fields.at(i).*; i -= fields.len; }, } @@ -1830,7 +1824,7 @@ pub const Node = struct { pub fn iterate(self: &BuiltinCall, index: usize) ?&Node { var i = index; - if (i < self.params.len) return *self.params.at(i); + if (i < self.params.len) return self.params.at(i).*; i -= self.params.len; return null; @@ -1873,11 +1867,11 @@ pub const Node = struct { } pub fn firstToken(self: &MultilineStringLiteral) TokenIndex { - return *self.lines.at(0); + return self.lines.at(0).*; } pub fn lastToken(self: &MultilineStringLiteral) TokenIndex { - return *self.lines.at(self.lines.len - 1); + return self.lines.at(self.lines.len - 1).*; } }; @@ -1974,7 +1968,7 @@ pub const Node = struct { const Kind = union(enum) { Variable: &Identifier, - Return: &Node + Return: &Node, }; pub fn iterate(self: &AsmOutput, index: usize) ?&Node { @@ -1994,7 +1988,7 @@ pub const Node = struct { Kind.Return => |return_type| { if (i < 1) return return_type; i -= 1; - } + }, } return null; @@ -2059,13 +2053,13 @@ pub const Node = struct { pub fn iterate(self: &Asm, index: usize) ?&Node { var i = index; - if (i < self.outputs.len) return &(*self.outputs.at(index)).base; + if (i < self.outputs.len) return &(self.outputs.at(index).*).base; i -= self.outputs.len; - if (i < self.inputs.len) return &(*self.inputs.at(index)).base; + if (i < self.inputs.len) return &(self.inputs.at(index).*).base; i -= self.inputs.len; - if (i < self.clobbers.len) return *self.clobbers.at(index); + if (i < self.clobbers.len) return self.clobbers.at(index).*; i -= self.clobbers.len; return null; @@ -2159,11 +2153,11 @@ pub const Node = struct { } pub fn firstToken(self: &DocComment) TokenIndex { - return *self.lines.at(0); + return self.lines.at(0).*; } pub fn lastToken(self: &DocComment) TokenIndex { - return *self.lines.at(self.lines.len - 1); + return self.lines.at(self.lines.len - 1).*; } }; @@ -2192,4 +2186,3 @@ pub const Node = struct { } }; }; - diff --git a/std/zig/parse.zig b/std/zig/parse.zig index f2376f0df310261df14f7b1579a5281f2996f7b0..04aeeccaeb454119c33b2d3e7c4264b0436df893 100644 --- a/std/zig/parse.zig +++ b/std/zig/parse.zig @@ -17,15 +17,15 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { defer stack.deinit(); const arena = &tree_arena.allocator; - const root_node = try arena.construct(ast.Node.Root { - .base = ast.Node { .id = ast.Node.Id.Root }, + const root_node = try arena.construct(ast.Node.Root{ + .base = ast.Node{ .id = ast.Node.Id.Root }, .decls = ast.Node.Root.DeclList.init(arena), .doc_comments = null, // initialized when we get the eof token .eof_token = undefined, }); - var tree = ast.Tree { + var tree = ast.Tree{ .source = source, .root_node = root_node, .arena_allocator = tree_arena, @@ -36,9 +36,8 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { var tokenizer = Tokenizer.init(tree.source); while (true) { const token_ptr = try tree.tokens.addOne(); - *token_ptr = tokenizer.next(); - if (token_ptr.id == Token.Id.Eof) - break; + token_ptr.* = tokenizer.next(); + if (token_ptr.id == Token.Id.Eof) break; } var tok_it = tree.tokens.iterator(0); @@ -63,33 +62,27 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { Token.Id.Keyword_test => { stack.append(State.TopLevel) catch unreachable; - const block = try arena.construct(ast.Node.Block { - .base = ast.Node { - .id = ast.Node.Id.Block, - }, + const block = try arena.construct(ast.Node.Block{ + .base = ast.Node{ .id = ast.Node.Id.Block }, .label = null, .lbrace = undefined, .statements = ast.Node.Block.StatementList.init(arena), .rbrace = undefined, }); - const test_node = try arena.construct(ast.Node.TestDecl { - .base = ast.Node { - .id = ast.Node.Id.TestDecl, - }, + const test_node = try arena.construct(ast.Node.TestDecl{ + .base = ast.Node{ .id = ast.Node.Id.TestDecl }, .doc_comments = comments, .test_token = token_index, .name = undefined, .body_node = &block.base, }); try root_node.decls.push(&test_node.base); - try stack.append(State { .Block = block }); - try stack.append(State { - .ExpectTokenSave = ExpectTokenSave { - .id = Token.Id.LBrace, - .ptr = &block.rbrace, - } - }); - try stack.append(State { .StringLiteral = OptionalCtx { .Required = &test_node.name } }); + try stack.append(State{ .Block = block }); + try stack.append(State{ .ExpectTokenSave = ExpectTokenSave{ + .id = Token.Id.LBrace, + .ptr = &block.rbrace, + } }); + try stack.append(State{ .StringLiteral = OptionalCtx{ .Required = &test_node.name } }); continue; }, Token.Id.Eof => { @@ -99,29 +92,25 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { }, Token.Id.Keyword_pub => { stack.append(State.TopLevel) catch unreachable; - try stack.append(State { - .TopLevelExtern = TopLevelDeclCtx { - .decls = &root_node.decls, - .visib_token = token_index, - .extern_export_inline_token = null, - .lib_name = null, - .comments = comments, - } - }); + try stack.append(State{ .TopLevelExtern = TopLevelDeclCtx{ + .decls = &root_node.decls, + .visib_token = token_index, + .extern_export_inline_token = null, + .lib_name = null, + .comments = comments, + } }); continue; }, Token.Id.Keyword_comptime => { - const block = try arena.construct(ast.Node.Block { - .base = ast.Node {.id = ast.Node.Id.Block }, + const block = try arena.construct(ast.Node.Block{ + .base = ast.Node{ .id = ast.Node.Id.Block }, .label = null, .lbrace = undefined, .statements = ast.Node.Block.StatementList.init(arena), .rbrace = undefined, }); - const node = try arena.construct(ast.Node.Comptime { - .base = ast.Node { - .id = ast.Node.Id.Comptime, - }, + const node = try arena.construct(ast.Node.Comptime{ + .base = ast.Node{ .id = ast.Node.Id.Comptime }, .comptime_token = token_index, .expr = &block.base, .doc_comments = comments, @@ -129,27 +118,23 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { try root_node.decls.push(&node.base); stack.append(State.TopLevel) catch unreachable; - try stack.append(State { .Block = block }); - try stack.append(State { - .ExpectTokenSave = ExpectTokenSave { - .id = Token.Id.LBrace, - .ptr = &block.rbrace, - } - }); + try stack.append(State{ .Block = block }); + try stack.append(State{ .ExpectTokenSave = ExpectTokenSave{ + .id = Token.Id.LBrace, + .ptr = &block.rbrace, + } }); continue; }, else => { putBackToken(&tok_it, &tree); stack.append(State.TopLevel) catch unreachable; - try stack.append(State { - .TopLevelExtern = TopLevelDeclCtx { - .decls = &root_node.decls, - .visib_token = null, - .extern_export_inline_token = null, - .lib_name = null, - .comments = comments, - } - }); + try stack.append(State{ .TopLevelExtern = TopLevelDeclCtx{ + .decls = &root_node.decls, + .visib_token = null, + .extern_export_inline_token = null, + .lib_name = null, + .comments = comments, + } }); continue; }, } @@ -159,41 +144,38 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { const token_index = token.index; const token_ptr = token.ptr; switch (token_ptr.id) { - Token.Id.Keyword_export, Token.Id.Keyword_inline => { - stack.append(State { - .TopLevelDecl = TopLevelDeclCtx { - .decls = ctx.decls, - .visib_token = ctx.visib_token, - .extern_export_inline_token = AnnotatedToken { - .index = token_index, - .ptr = token_ptr, - }, - .lib_name = null, - .comments = ctx.comments, + Token.Id.Keyword_export, + Token.Id.Keyword_inline => { + stack.append(State{ .TopLevelDecl = TopLevelDeclCtx{ + .decls = ctx.decls, + .visib_token = ctx.visib_token, + .extern_export_inline_token = AnnotatedToken{ + .index = token_index, + .ptr = token_ptr, }, - }) catch unreachable; + .lib_name = null, + .comments = ctx.comments, + } }) catch unreachable; continue; }, Token.Id.Keyword_extern => { - stack.append(State { - .TopLevelLibname = TopLevelDeclCtx { - .decls = ctx.decls, - .visib_token = ctx.visib_token, - .extern_export_inline_token = AnnotatedToken { - .index = token_index, - .ptr = token_ptr, - }, - .lib_name = null, - .comments = ctx.comments, + stack.append(State{ .TopLevelLibname = TopLevelDeclCtx{ + .decls = ctx.decls, + .visib_token = ctx.visib_token, + .extern_export_inline_token = AnnotatedToken{ + .index = token_index, + .ptr = token_ptr, }, - }) catch unreachable; + .lib_name = null, + .comments = ctx.comments, + } }) catch unreachable; continue; }, else => { putBackToken(&tok_it, &tree); - stack.append(State { .TopLevelDecl = ctx }) catch unreachable; + stack.append(State{ .TopLevelDecl = ctx }) catch unreachable; continue; - } + }, } }, State.TopLevelLibname => |ctx| { @@ -207,15 +189,13 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { }; }; - stack.append(State { - .TopLevelDecl = TopLevelDeclCtx { - .decls = ctx.decls, - .visib_token = ctx.visib_token, - .extern_export_inline_token = ctx.extern_export_inline_token, - .lib_name = lib_name, - .comments = ctx.comments, - }, - }) catch unreachable; + stack.append(State{ .TopLevelDecl = TopLevelDeclCtx{ + .decls = ctx.decls, + .visib_token = ctx.visib_token, + .extern_export_inline_token = ctx.extern_export_inline_token, + .lib_name = lib_name, + .comments = ctx.comments, + } }) catch unreachable; continue; }, State.TopLevelDecl => |ctx| { @@ -225,14 +205,12 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { switch (token_ptr.id) { Token.Id.Keyword_use => { if (ctx.extern_export_inline_token) |annotated_token| { - *(try tree.errors.addOne()) = Error { - .InvalidToken = Error.InvalidToken { .token = annotated_token.index }, - }; + ((try tree.errors.addOne())).* = Error{ .InvalidToken = Error.InvalidToken{ .token = annotated_token.index } }; return tree; } - const node = try arena.construct(ast.Node.Use { - .base = ast.Node {.id = ast.Node.Id.Use }, + const node = try arena.construct(ast.Node.Use{ + .base = ast.Node{ .id = ast.Node.Id.Use }, .visib_token = ctx.visib_token, .expr = undefined, .semicolon_token = undefined, @@ -240,44 +218,39 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { }); try ctx.decls.push(&node.base); - stack.append(State { - .ExpectTokenSave = ExpectTokenSave { - .id = Token.Id.Semicolon, - .ptr = &node.semicolon_token, - } - }) catch unreachable; - try stack.append(State { .Expression = OptionalCtx { .Required = &node.expr } }); + stack.append(State{ .ExpectTokenSave = ExpectTokenSave{ + .id = Token.Id.Semicolon, + .ptr = &node.semicolon_token, + } }) catch unreachable; + try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.expr } }); continue; }, - Token.Id.Keyword_var, Token.Id.Keyword_const => { + Token.Id.Keyword_var, + Token.Id.Keyword_const => { if (ctx.extern_export_inline_token) |annotated_token| { if (annotated_token.ptr.id == Token.Id.Keyword_inline) { - *(try tree.errors.addOne()) = Error { - .InvalidToken = Error.InvalidToken { .token = annotated_token.index }, - }; + ((try tree.errors.addOne())).* = Error{ .InvalidToken = Error.InvalidToken{ .token = annotated_token.index } }; return tree; } } - try stack.append(State { - .VarDecl = VarDeclCtx { - .comments = ctx.comments, - .visib_token = ctx.visib_token, - .lib_name = ctx.lib_name, - .comptime_token = null, - .extern_export_token = if (ctx.extern_export_inline_token) |at| at.index else null, - .mut_token = token_index, - .list = ctx.decls - } - }); + try stack.append(State{ .VarDecl = VarDeclCtx{ + .comments = ctx.comments, + .visib_token = ctx.visib_token, + .lib_name = ctx.lib_name, + .comptime_token = null, + .extern_export_token = if (ctx.extern_export_inline_token) |at| at.index else null, + .mut_token = token_index, + .list = ctx.decls, + } }); continue; }, - Token.Id.Keyword_fn, Token.Id.Keyword_nakedcc, - Token.Id.Keyword_stdcallcc, Token.Id.Keyword_async => { - const fn_proto = try arena.construct(ast.Node.FnProto { - .base = ast.Node { - .id = ast.Node.Id.FnProto, - }, + Token.Id.Keyword_fn, + Token.Id.Keyword_nakedcc, + Token.Id.Keyword_stdcallcc, + Token.Id.Keyword_async => { + const fn_proto = try arena.construct(ast.Node.FnProto{ + .base = ast.Node{ .id = ast.Node.Id.FnProto }, .doc_comments = ctx.comments, .visib_token = ctx.visib_token, .name_token = null, @@ -293,36 +266,33 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { .align_expr = null, }); try ctx.decls.push(&fn_proto.base); - stack.append(State { .FnDef = fn_proto }) catch unreachable; - try stack.append(State { .FnProto = fn_proto }); + stack.append(State{ .FnDef = fn_proto }) catch unreachable; + try stack.append(State{ .FnProto = fn_proto }); switch (token_ptr.id) { - Token.Id.Keyword_nakedcc, Token.Id.Keyword_stdcallcc => { + Token.Id.Keyword_nakedcc, + Token.Id.Keyword_stdcallcc => { fn_proto.cc_token = token_index; - try stack.append(State { - .ExpectTokenSave = ExpectTokenSave { - .id = Token.Id.Keyword_fn, - .ptr = &fn_proto.fn_token, - } - }); + try stack.append(State{ .ExpectTokenSave = ExpectTokenSave{ + .id = Token.Id.Keyword_fn, + .ptr = &fn_proto.fn_token, + } }); continue; }, Token.Id.Keyword_async => { - const async_node = try arena.construct(ast.Node.AsyncAttribute { - .base = ast.Node {.id = ast.Node.Id.AsyncAttribute }, + const async_node = try arena.construct(ast.Node.AsyncAttribute{ + .base = ast.Node{ .id = ast.Node.Id.AsyncAttribute }, .async_token = token_index, .allocator_type = null, .rangle_bracket = null, }); fn_proto.async_attr = async_node; - try stack.append(State { - .ExpectTokenSave = ExpectTokenSave { - .id = Token.Id.Keyword_fn, - .ptr = &fn_proto.fn_token, - } - }); - try stack.append(State { .AsyncAllocator = async_node }); + try stack.append(State{ .ExpectTokenSave = ExpectTokenSave{ + .id = Token.Id.Keyword_fn, + .ptr = &fn_proto.fn_token, + } }); + try stack.append(State{ .AsyncAllocator = async_node }); continue; }, Token.Id.Keyword_fn => { @@ -333,9 +303,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { } }, else => { - *(try tree.errors.addOne()) = Error { - .ExpectedVarDeclOrFn = Error.ExpectedVarDeclOrFn { .token = token_index }, - }; + ((try tree.errors.addOne())).* = Error{ .ExpectedVarDeclOrFn = Error.ExpectedVarDeclOrFn{ .token = token_index } }; return tree; }, } @@ -343,34 +311,30 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { State.TopLevelExternOrField => |ctx| { if (eatToken(&tok_it, &tree, Token.Id.Identifier)) |identifier| { std.debug.assert(ctx.container_decl.kind == ast.Node.ContainerDecl.Kind.Struct); - const node = try arena.construct(ast.Node.StructField { - .base = ast.Node { - .id = ast.Node.Id.StructField, - }, + const node = try arena.construct(ast.Node.StructField{ + .base = ast.Node{ .id = ast.Node.Id.StructField }, .doc_comments = ctx.comments, .visib_token = ctx.visib_token, .name_token = identifier, .type_expr = undefined, }); const node_ptr = try ctx.container_decl.fields_and_decls.addOne(); - *node_ptr = &node.base; + node_ptr.* = &node.base; - stack.append(State { .FieldListCommaOrEnd = ctx.container_decl }) catch unreachable; - try stack.append(State { .Expression = OptionalCtx { .Required = &node.type_expr } }); - try stack.append(State { .ExpectToken = Token.Id.Colon }); + stack.append(State{ .FieldListCommaOrEnd = ctx.container_decl }) catch unreachable; + try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.type_expr } }); + try stack.append(State{ .ExpectToken = Token.Id.Colon }); continue; } stack.append(State{ .ContainerDecl = ctx.container_decl }) catch unreachable; - try stack.append(State { - .TopLevelExtern = TopLevelDeclCtx { - .decls = &ctx.container_decl.fields_and_decls, - .visib_token = ctx.visib_token, - .extern_export_inline_token = null, - .lib_name = null, - .comments = ctx.comments, - } - }); + try stack.append(State{ .TopLevelExtern = TopLevelDeclCtx{ + .decls = &ctx.container_decl.fields_and_decls, + .visib_token = ctx.visib_token, + .extern_export_inline_token = null, + .lib_name = null, + .comments = ctx.comments, + } }); continue; }, @@ -382,7 +346,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { putBackToken(&tok_it, &tree); continue; } - stack.append(State { .Expression = ctx }) catch unreachable; + stack.append(State{ .Expression = ctx }) catch unreachable; continue; }, @@ -390,8 +354,8 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { const token = nextToken(&tok_it, &tree); const token_index = token.index; const token_ptr = token.ptr; - const node = try arena.construct(ast.Node.ContainerDecl { - .base = ast.Node {.id = ast.Node.Id.ContainerDecl }, + const node = try arena.construct(ast.Node.ContainerDecl{ + .base = ast.Node{ .id = ast.Node.Id.ContainerDecl }, .ltoken = ctx.ltoken, .layout = ctx.layout, .kind = switch (token_ptr.id) { @@ -399,9 +363,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { Token.Id.Keyword_union => ast.Node.ContainerDecl.Kind.Union, Token.Id.Keyword_enum => ast.Node.ContainerDecl.Kind.Enum, else => { - *(try tree.errors.addOne()) = Error { - .ExpectedAggregateKw = Error.ExpectedAggregateKw { .token = token_index }, - }; + ((try tree.errors.addOne())).* = Error{ .ExpectedAggregateKw = Error.ExpectedAggregateKw{ .token = token_index } }; return tree; }, }, @@ -411,9 +373,9 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { }); ctx.opt_ctx.store(&node.base); - stack.append(State { .ContainerDecl = node }) catch unreachable; - try stack.append(State { .ExpectToken = Token.Id.LBrace }); - try stack.append(State { .ContainerInitArgStart = node }); + stack.append(State{ .ContainerDecl = node }) catch unreachable; + try stack.append(State{ .ExpectToken = Token.Id.LBrace }); + try stack.append(State{ .ContainerInitArgStart = node }); continue; }, @@ -422,8 +384,8 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { continue; } - stack.append(State { .ExpectToken = Token.Id.RParen }) catch unreachable; - try stack.append(State { .ContainerInitArg = container_decl }); + stack.append(State{ .ExpectToken = Token.Id.RParen }) catch unreachable; + try stack.append(State{ .ContainerInitArg = container_decl }); continue; }, @@ -433,23 +395,21 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { const init_arg_token_ptr = init_arg_token.ptr; switch (init_arg_token_ptr.id) { Token.Id.Keyword_enum => { - container_decl.init_arg_expr = ast.Node.ContainerDecl.InitArg {.Enum = null}; + container_decl.init_arg_expr = ast.Node.ContainerDecl.InitArg{ .Enum = null }; const lparen_tok = nextToken(&tok_it, &tree); const lparen_tok_index = lparen_tok.index; const lparen_tok_ptr = lparen_tok.ptr; if (lparen_tok_ptr.id == Token.Id.LParen) { - try stack.append(State { .ExpectToken = Token.Id.RParen } ); - try stack.append(State { .Expression = OptionalCtx { - .RequiredNull = &container_decl.init_arg_expr.Enum, - } }); + try stack.append(State{ .ExpectToken = Token.Id.RParen }); + try stack.append(State{ .Expression = OptionalCtx{ .RequiredNull = &container_decl.init_arg_expr.Enum } }); } else { putBackToken(&tok_it, &tree); } }, else => { putBackToken(&tok_it, &tree); - container_decl.init_arg_expr = ast.Node.ContainerDecl.InitArg { .Type = undefined }; - stack.append(State { .Expression = OptionalCtx { .Required = &container_decl.init_arg_expr.Type } }) catch unreachable; + container_decl.init_arg_expr = ast.Node.ContainerDecl.InitArg{ .Type = undefined }; + stack.append(State{ .Expression = OptionalCtx{ .Required = &container_decl.init_arg_expr.Type } }) catch unreachable; }, } continue; @@ -468,26 +428,24 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { Token.Id.Identifier => { switch (container_decl.kind) { ast.Node.ContainerDecl.Kind.Struct => { - const node = try arena.construct(ast.Node.StructField { - .base = ast.Node { - .id = ast.Node.Id.StructField, - }, + const node = try arena.construct(ast.Node.StructField{ + .base = ast.Node{ .id = ast.Node.Id.StructField }, .doc_comments = comments, .visib_token = null, .name_token = token_index, .type_expr = undefined, }); const node_ptr = try container_decl.fields_and_decls.addOne(); - *node_ptr = &node.base; + node_ptr.* = &node.base; - try stack.append(State { .FieldListCommaOrEnd = container_decl }); - try stack.append(State { .TypeExprBegin = OptionalCtx { .Required = &node.type_expr } }); - try stack.append(State { .ExpectToken = Token.Id.Colon }); + try stack.append(State{ .FieldListCommaOrEnd = container_decl }); + try stack.append(State{ .TypeExprBegin = OptionalCtx{ .Required = &node.type_expr } }); + try stack.append(State{ .ExpectToken = Token.Id.Colon }); continue; }, ast.Node.ContainerDecl.Kind.Union => { - const node = try arena.construct(ast.Node.UnionTag { - .base = ast.Node {.id = ast.Node.Id.UnionTag }, + const node = try arena.construct(ast.Node.UnionTag{ + .base = ast.Node{ .id = ast.Node.Id.UnionTag }, .name_token = token_index, .type_expr = null, .value_expr = null, @@ -495,24 +453,24 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { }); try container_decl.fields_and_decls.push(&node.base); - stack.append(State { .FieldListCommaOrEnd = container_decl }) catch unreachable; - try stack.append(State { .FieldInitValue = OptionalCtx { .RequiredNull = &node.value_expr } }); - try stack.append(State { .TypeExprBegin = OptionalCtx { .RequiredNull = &node.type_expr } }); - try stack.append(State { .IfToken = Token.Id.Colon }); + stack.append(State{ .FieldListCommaOrEnd = container_decl }) catch unreachable; + try stack.append(State{ .FieldInitValue = OptionalCtx{ .RequiredNull = &node.value_expr } }); + try stack.append(State{ .TypeExprBegin = OptionalCtx{ .RequiredNull = &node.type_expr } }); + try stack.append(State{ .IfToken = Token.Id.Colon }); continue; }, ast.Node.ContainerDecl.Kind.Enum => { - const node = try arena.construct(ast.Node.EnumTag { - .base = ast.Node { .id = ast.Node.Id.EnumTag }, + const node = try arena.construct(ast.Node.EnumTag{ + .base = ast.Node{ .id = ast.Node.Id.EnumTag }, .name_token = token_index, .value = null, .doc_comments = comments, }); try container_decl.fields_and_decls.push(&node.base); - stack.append(State { .FieldListCommaOrEnd = container_decl }) catch unreachable; - try stack.append(State { .Expression = OptionalCtx { .RequiredNull = &node.value } }); - try stack.append(State { .IfToken = Token.Id.Equal }); + stack.append(State{ .FieldListCommaOrEnd = container_decl }) catch unreachable; + try stack.append(State{ .Expression = OptionalCtx{ .RequiredNull = &node.value } }); + try stack.append(State{ .IfToken = Token.Id.Equal }); continue; }, } @@ -520,48 +478,40 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { Token.Id.Keyword_pub => { switch (container_decl.kind) { ast.Node.ContainerDecl.Kind.Struct => { - try stack.append(State { - .TopLevelExternOrField = TopLevelExternOrFieldCtx { - .visib_token = token_index, - .container_decl = container_decl, - .comments = comments, - } - }); + try stack.append(State{ .TopLevelExternOrField = TopLevelExternOrFieldCtx{ + .visib_token = token_index, + .container_decl = container_decl, + .comments = comments, + } }); continue; }, else => { stack.append(State{ .ContainerDecl = container_decl }) catch unreachable; - try stack.append(State { - .TopLevelExtern = TopLevelDeclCtx { - .decls = &container_decl.fields_and_decls, - .visib_token = token_index, - .extern_export_inline_token = null, - .lib_name = null, - .comments = comments, - } - }); + try stack.append(State{ .TopLevelExtern = TopLevelDeclCtx{ + .decls = &container_decl.fields_and_decls, + .visib_token = token_index, + .extern_export_inline_token = null, + .lib_name = null, + .comments = comments, + } }); continue; - } + }, } }, Token.Id.Keyword_export => { stack.append(State{ .ContainerDecl = container_decl }) catch unreachable; - try stack.append(State { - .TopLevelExtern = TopLevelDeclCtx { - .decls = &container_decl.fields_and_decls, - .visib_token = token_index, - .extern_export_inline_token = null, - .lib_name = null, - .comments = comments, - } - }); + try stack.append(State{ .TopLevelExtern = TopLevelDeclCtx{ + .decls = &container_decl.fields_and_decls, + .visib_token = token_index, + .extern_export_inline_token = null, + .lib_name = null, + .comments = comments, + } }); continue; }, Token.Id.RBrace => { if (comments != null) { - *(try tree.errors.addOne()) = Error { - .UnattachedDocComment = Error.UnattachedDocComment { .token = token_index }, - }; + ((try tree.errors.addOne())).* = Error{ .UnattachedDocComment = Error.UnattachedDocComment{ .token = token_index } }; return tree; } container_decl.rbrace_token = token_index; @@ -570,26 +520,21 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { else => { putBackToken(&tok_it, &tree); stack.append(State{ .ContainerDecl = container_decl }) catch unreachable; - try stack.append(State { - .TopLevelExtern = TopLevelDeclCtx { - .decls = &container_decl.fields_and_decls, - .visib_token = null, - .extern_export_inline_token = null, - .lib_name = null, - .comments = comments, - } - }); + try stack.append(State{ .TopLevelExtern = TopLevelDeclCtx{ + .decls = &container_decl.fields_and_decls, + .visib_token = null, + .extern_export_inline_token = null, + .lib_name = null, + .comments = comments, + } }); continue; - } + }, } }, - State.VarDecl => |ctx| { - const var_decl = try arena.construct(ast.Node.VarDecl { - .base = ast.Node { - .id = ast.Node.Id.VarDecl, - }, + const var_decl = try arena.construct(ast.Node.VarDecl{ + .base = ast.Node{ .id = ast.Node.Id.VarDecl }, .doc_comments = ctx.comments, .visib_token = ctx.visib_token, .mut_token = ctx.mut_token, @@ -606,27 +551,25 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { }); try ctx.list.push(&var_decl.base); - try stack.append(State { .VarDeclAlign = var_decl }); - try stack.append(State { .TypeExprBegin = OptionalCtx { .RequiredNull = &var_decl.type_node} }); - try stack.append(State { .IfToken = Token.Id.Colon }); - try stack.append(State { - .ExpectTokenSave = ExpectTokenSave { - .id = Token.Id.Identifier, - .ptr = &var_decl.name_token, - } - }); + try stack.append(State{ .VarDeclAlign = var_decl }); + try stack.append(State{ .TypeExprBegin = OptionalCtx{ .RequiredNull = &var_decl.type_node } }); + try stack.append(State{ .IfToken = Token.Id.Colon }); + try stack.append(State{ .ExpectTokenSave = ExpectTokenSave{ + .id = Token.Id.Identifier, + .ptr = &var_decl.name_token, + } }); continue; }, State.VarDeclAlign => |var_decl| { - try stack.append(State { .VarDeclEq = var_decl }); + try stack.append(State{ .VarDeclEq = var_decl }); const next_token = nextToken(&tok_it, &tree); const next_token_index = next_token.index; const next_token_ptr = next_token.ptr; if (next_token_ptr.id == Token.Id.Keyword_align) { - try stack.append(State { .ExpectToken = Token.Id.RParen }); - try stack.append(State { .Expression = OptionalCtx { .RequiredNull = &var_decl.align_node} }); - try stack.append(State { .ExpectToken = Token.Id.LParen }); + try stack.append(State{ .ExpectToken = Token.Id.RParen }); + try stack.append(State{ .Expression = OptionalCtx{ .RequiredNull = &var_decl.align_node } }); + try stack.append(State{ .ExpectToken = Token.Id.LParen }); continue; } @@ -640,8 +583,8 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { switch (token_ptr.id) { Token.Id.Equal => { var_decl.eq_token = token_index; - stack.append(State { .VarDeclSemiColon = var_decl }) catch unreachable; - try stack.append(State { .Expression = OptionalCtx { .RequiredNull = &var_decl.init_node } }); + stack.append(State{ .VarDeclSemiColon = var_decl }) catch unreachable; + try stack.append(State{ .Expression = OptionalCtx{ .RequiredNull = &var_decl.init_node } }); continue; }, Token.Id.Semicolon => { @@ -649,11 +592,9 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { continue; }, else => { - *(try tree.errors.addOne()) = Error { - .ExpectedEqOrSemi = Error.ExpectedEqOrSemi { .token = token_index }, - }; + ((try tree.errors.addOne())).* = Error{ .ExpectedEqOrSemi = Error.ExpectedEqOrSemi{ .token = token_index } }; return tree; - } + }, } }, @@ -661,12 +602,10 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { const semicolon_token = nextToken(&tok_it, &tree); if (semicolon_token.ptr.id != Token.Id.Semicolon) { - *(try tree.errors.addOne()) = Error { - .ExpectedToken = Error.ExpectedToken { - .token = semicolon_token.index, - .expected_id = Token.Id.Semicolon, - }, - }; + ((try tree.errors.addOne())).* = Error{ .ExpectedToken = Error.ExpectedToken{ + .token = semicolon_token.index, + .expected_id = Token.Id.Semicolon, + } }; return tree; } @@ -686,32 +625,30 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { const token = nextToken(&tok_it, &tree); const token_index = token.index; const token_ptr = token.ptr; - switch(token_ptr.id) { + switch (token_ptr.id) { Token.Id.LBrace => { - const block = try arena.construct(ast.Node.Block { - .base = ast.Node { .id = ast.Node.Id.Block }, + const block = try arena.construct(ast.Node.Block{ + .base = ast.Node{ .id = ast.Node.Id.Block }, .label = null, .lbrace = token_index, .statements = ast.Node.Block.StatementList.init(arena), .rbrace = undefined, }); fn_proto.body_node = &block.base; - stack.append(State { .Block = block }) catch unreachable; + stack.append(State{ .Block = block }) catch unreachable; continue; }, Token.Id.Semicolon => continue, else => { - *(try tree.errors.addOne()) = Error { - .ExpectedSemiOrLBrace = Error.ExpectedSemiOrLBrace { .token = token_index }, - }; + ((try tree.errors.addOne())).* = Error{ .ExpectedSemiOrLBrace = Error.ExpectedSemiOrLBrace{ .token = token_index } }; return tree; }, } }, State.FnProto => |fn_proto| { - stack.append(State { .FnProtoAlign = fn_proto }) catch unreachable; - try stack.append(State { .ParamDecl = fn_proto }); - try stack.append(State { .ExpectToken = Token.Id.LParen }); + stack.append(State{ .FnProtoAlign = fn_proto }) catch unreachable; + try stack.append(State{ .ParamDecl = fn_proto }); + try stack.append(State{ .ExpectToken = Token.Id.LParen }); if (eatToken(&tok_it, &tree, Token.Id.Identifier)) |name_token| { fn_proto.name_token = name_token; @@ -719,12 +656,12 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { continue; }, State.FnProtoAlign => |fn_proto| { - stack.append(State { .FnProtoReturnType = fn_proto }) catch unreachable; + stack.append(State{ .FnProtoReturnType = fn_proto }) catch unreachable; if (eatToken(&tok_it, &tree, Token.Id.Keyword_align)) |align_token| { - try stack.append(State { .ExpectToken = Token.Id.RParen }); - try stack.append(State { .Expression = OptionalCtx { .RequiredNull = &fn_proto.align_expr } }); - try stack.append(State { .ExpectToken = Token.Id.LParen }); + try stack.append(State{ .ExpectToken = Token.Id.RParen }); + try stack.append(State{ .Expression = OptionalCtx{ .RequiredNull = &fn_proto.align_expr } }); + try stack.append(State{ .ExpectToken = Token.Id.LParen }); } continue; }, @@ -734,42 +671,37 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { const token_ptr = token.ptr; switch (token_ptr.id) { Token.Id.Bang => { - fn_proto.return_type = ast.Node.FnProto.ReturnType { .InferErrorSet = undefined }; - stack.append(State { - .TypeExprBegin = OptionalCtx { .Required = &fn_proto.return_type.InferErrorSet }, - }) catch unreachable; + fn_proto.return_type = ast.Node.FnProto.ReturnType{ .InferErrorSet = undefined }; + stack.append(State{ .TypeExprBegin = OptionalCtx{ .Required = &fn_proto.return_type.InferErrorSet } }) catch unreachable; continue; }, else => { // TODO: this is a special case. Remove this when #760 is fixed if (token_ptr.id == Token.Id.Keyword_error) { if ((??tok_it.peek()).id == Token.Id.LBrace) { - const error_type_node = try arena.construct(ast.Node.ErrorType { - .base = ast.Node { .id = ast.Node.Id.ErrorType }, + const error_type_node = try arena.construct(ast.Node.ErrorType{ + .base = ast.Node{ .id = ast.Node.Id.ErrorType }, .token = token_index, }); - fn_proto.return_type = ast.Node.FnProto.ReturnType { - .Explicit = &error_type_node.base, - }; + fn_proto.return_type = ast.Node.FnProto.ReturnType{ .Explicit = &error_type_node.base }; continue; } } putBackToken(&tok_it, &tree); - fn_proto.return_type = ast.Node.FnProto.ReturnType { .Explicit = undefined }; - stack.append(State { .TypeExprBegin = OptionalCtx { .Required = &fn_proto.return_type.Explicit }, }) catch unreachable; + fn_proto.return_type = ast.Node.FnProto.ReturnType{ .Explicit = undefined }; + stack.append(State{ .TypeExprBegin = OptionalCtx{ .Required = &fn_proto.return_type.Explicit } }) catch unreachable; continue; }, } }, - State.ParamDecl => |fn_proto| { if (eatToken(&tok_it, &tree, Token.Id.RParen)) |_| { continue; } - const param_decl = try arena.construct(ast.Node.ParamDecl { - .base = ast.Node {.id = ast.Node.Id.ParamDecl }, + const param_decl = try arena.construct(ast.Node.ParamDecl{ + .base = ast.Node{ .id = ast.Node.Id.ParamDecl }, .comptime_token = null, .noalias_token = null, .name_token = null, @@ -778,14 +710,12 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { }); try fn_proto.params.push(¶m_decl.base); - stack.append(State { - .ParamDeclEnd = ParamDeclEndCtx { - .param_decl = param_decl, - .fn_proto = fn_proto, - } - }) catch unreachable; - try stack.append(State { .ParamDeclName = param_decl }); - try stack.append(State { .ParamDeclAliasOrComptime = param_decl }); + stack.append(State{ .ParamDeclEnd = ParamDeclEndCtx{ + .param_decl = param_decl, + .fn_proto = fn_proto, + } }) catch unreachable; + try stack.append(State{ .ParamDeclName = param_decl }); + try stack.append(State{ .ParamDeclAliasOrComptime = param_decl }); continue; }, State.ParamDeclAliasOrComptime => |param_decl| { @@ -811,21 +741,19 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { State.ParamDeclEnd => |ctx| { if (eatToken(&tok_it, &tree, Token.Id.Ellipsis3)) |ellipsis3| { ctx.param_decl.var_args_token = ellipsis3; - stack.append(State { .ExpectToken = Token.Id.RParen }) catch unreachable; + stack.append(State{ .ExpectToken = Token.Id.RParen }) catch unreachable; continue; } - try stack.append(State { .ParamDeclComma = ctx.fn_proto }); - try stack.append(State { - .TypeExprBegin = OptionalCtx { .Required = &ctx.param_decl.type_node } - }); + try stack.append(State{ .ParamDeclComma = ctx.fn_proto }); + try stack.append(State{ .TypeExprBegin = OptionalCtx{ .Required = &ctx.param_decl.type_node } }); continue; }, State.ParamDeclComma => |fn_proto| { switch (expectCommaOrEnd(&tok_it, &tree, Token.Id.RParen)) { ExpectCommaOrEndResult.end_token => |t| { if (t == null) { - stack.append(State { .ParamDecl = fn_proto }) catch unreachable; + stack.append(State{ .ParamDecl = fn_proto }) catch unreachable; } continue; }, @@ -838,12 +766,10 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { State.MaybeLabeledExpression => |ctx| { if (eatToken(&tok_it, &tree, Token.Id.Colon)) |_| { - stack.append(State { - .LabeledExpression = LabelCtx { - .label = ctx.label, - .opt_ctx = ctx.opt_ctx, - } - }) catch unreachable; + stack.append(State{ .LabeledExpression = LabelCtx{ + .label = ctx.label, + .opt_ctx = ctx.opt_ctx, + } }) catch unreachable; continue; } @@ -856,69 +782,59 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { const token_ptr = token.ptr; switch (token_ptr.id) { Token.Id.LBrace => { - const block = try arena.construct(ast.Node.Block { - .base = ast.Node {.id = ast.Node.Id.Block}, + const block = try arena.construct(ast.Node.Block{ + .base = ast.Node{ .id = ast.Node.Id.Block }, .label = ctx.label, .lbrace = token_index, .statements = ast.Node.Block.StatementList.init(arena), .rbrace = undefined, }); ctx.opt_ctx.store(&block.base); - stack.append(State { .Block = block }) catch unreachable; + stack.append(State{ .Block = block }) catch unreachable; continue; }, Token.Id.Keyword_while => { - stack.append(State { - .While = LoopCtx { - .label = ctx.label, - .inline_token = null, - .loop_token = token_index, - .opt_ctx = ctx.opt_ctx.toRequired(), - } - }) catch unreachable; + stack.append(State{ .While = LoopCtx{ + .label = ctx.label, + .inline_token = null, + .loop_token = token_index, + .opt_ctx = ctx.opt_ctx.toRequired(), + } }) catch unreachable; continue; }, Token.Id.Keyword_for => { - stack.append(State { - .For = LoopCtx { - .label = ctx.label, - .inline_token = null, - .loop_token = token_index, - .opt_ctx = ctx.opt_ctx.toRequired(), - } - }) catch unreachable; + stack.append(State{ .For = LoopCtx{ + .label = ctx.label, + .inline_token = null, + .loop_token = token_index, + .opt_ctx = ctx.opt_ctx.toRequired(), + } }) catch unreachable; continue; }, Token.Id.Keyword_suspend => { - const node = try arena.construct(ast.Node.Suspend { - .base = ast.Node { - .id = ast.Node.Id.Suspend, - }, + const node = try arena.construct(ast.Node.Suspend{ + .base = ast.Node{ .id = ast.Node.Id.Suspend }, .label = ctx.label, .suspend_token = token_index, .payload = null, .body = null, }); ctx.opt_ctx.store(&node.base); - stack.append(State { .SuspendBody = node }) catch unreachable; - try stack.append(State { .Payload = OptionalCtx { .Optional = &node.payload } }); + stack.append(State{ .SuspendBody = node }) catch unreachable; + try stack.append(State{ .Payload = OptionalCtx{ .Optional = &node.payload } }); continue; }, Token.Id.Keyword_inline => { - stack.append(State { - .Inline = InlineCtx { - .label = ctx.label, - .inline_token = token_index, - .opt_ctx = ctx.opt_ctx.toRequired(), - } - }) catch unreachable; + stack.append(State{ .Inline = InlineCtx{ + .label = ctx.label, + .inline_token = token_index, + .opt_ctx = ctx.opt_ctx.toRequired(), + } }) catch unreachable; continue; }, else => { if (ctx.opt_ctx != OptionalCtx.Optional) { - *(try tree.errors.addOne()) = Error { - .ExpectedLabelable = Error.ExpectedLabelable { .token = token_index }, - }; + ((try tree.errors.addOne())).* = Error{ .ExpectedLabelable = Error.ExpectedLabelable{ .token = token_index } }; return tree; } @@ -933,32 +849,26 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { const token_ptr = token.ptr; switch (token_ptr.id) { Token.Id.Keyword_while => { - stack.append(State { - .While = LoopCtx { - .inline_token = ctx.inline_token, - .label = ctx.label, - .loop_token = token_index, - .opt_ctx = ctx.opt_ctx.toRequired(), - } - }) catch unreachable; + stack.append(State{ .While = LoopCtx{ + .inline_token = ctx.inline_token, + .label = ctx.label, + .loop_token = token_index, + .opt_ctx = ctx.opt_ctx.toRequired(), + } }) catch unreachable; continue; }, Token.Id.Keyword_for => { - stack.append(State { - .For = LoopCtx { - .inline_token = ctx.inline_token, - .label = ctx.label, - .loop_token = token_index, - .opt_ctx = ctx.opt_ctx.toRequired(), - } - }) catch unreachable; + stack.append(State{ .For = LoopCtx{ + .inline_token = ctx.inline_token, + .label = ctx.label, + .loop_token = token_index, + .opt_ctx = ctx.opt_ctx.toRequired(), + } }) catch unreachable; continue; }, else => { if (ctx.opt_ctx != OptionalCtx.Optional) { - *(try tree.errors.addOne()) = Error { - .ExpectedInlinable = Error.ExpectedInlinable { .token = token_index }, - }; + ((try tree.errors.addOne())).* = Error{ .ExpectedInlinable = Error.ExpectedInlinable{ .token = token_index } }; return tree; } @@ -968,8 +878,8 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { } }, State.While => |ctx| { - const node = try arena.construct(ast.Node.While { - .base = ast.Node {.id = ast.Node.Id.While }, + const node = try arena.construct(ast.Node.While{ + .base = ast.Node{ .id = ast.Node.Id.While }, .label = ctx.label, .inline_token = ctx.inline_token, .while_token = ctx.loop_token, @@ -980,25 +890,25 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { .@"else" = null, }); ctx.opt_ctx.store(&node.base); - stack.append(State { .Else = &node.@"else" }) catch unreachable; - try stack.append(State { .Expression = OptionalCtx { .Required = &node.body } }); - try stack.append(State { .WhileContinueExpr = &node.continue_expr }); - try stack.append(State { .IfToken = Token.Id.Colon }); - try stack.append(State { .PointerPayload = OptionalCtx { .Optional = &node.payload } }); - try stack.append(State { .ExpectToken = Token.Id.RParen }); - try stack.append(State { .Expression = OptionalCtx { .Required = &node.condition } }); - try stack.append(State { .ExpectToken = Token.Id.LParen }); + stack.append(State{ .Else = &node.@"else" }) catch unreachable; + try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.body } }); + try stack.append(State{ .WhileContinueExpr = &node.continue_expr }); + try stack.append(State{ .IfToken = Token.Id.Colon }); + try stack.append(State{ .PointerPayload = OptionalCtx{ .Optional = &node.payload } }); + try stack.append(State{ .ExpectToken = Token.Id.RParen }); + try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.condition } }); + try stack.append(State{ .ExpectToken = Token.Id.LParen }); continue; }, State.WhileContinueExpr => |dest| { - stack.append(State { .ExpectToken = Token.Id.RParen }) catch unreachable; - try stack.append(State { .AssignmentExpressionBegin = OptionalCtx { .RequiredNull = dest } }); - try stack.append(State { .ExpectToken = Token.Id.LParen }); + stack.append(State{ .ExpectToken = Token.Id.RParen }) catch unreachable; + try stack.append(State{ .AssignmentExpressionBegin = OptionalCtx{ .RequiredNull = dest } }); + try stack.append(State{ .ExpectToken = Token.Id.LParen }); continue; }, State.For => |ctx| { - const node = try arena.construct(ast.Node.For { - .base = ast.Node {.id = ast.Node.Id.For }, + const node = try arena.construct(ast.Node.For{ + .base = ast.Node{ .id = ast.Node.Id.For }, .label = ctx.label, .inline_token = ctx.inline_token, .for_token = ctx.loop_token, @@ -1008,33 +918,32 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { .@"else" = null, }); ctx.opt_ctx.store(&node.base); - stack.append(State { .Else = &node.@"else" }) catch unreachable; - try stack.append(State { .Expression = OptionalCtx { .Required = &node.body } }); - try stack.append(State { .PointerIndexPayload = OptionalCtx { .Optional = &node.payload } }); - try stack.append(State { .ExpectToken = Token.Id.RParen }); - try stack.append(State { .Expression = OptionalCtx { .Required = &node.array_expr } }); - try stack.append(State { .ExpectToken = Token.Id.LParen }); + stack.append(State{ .Else = &node.@"else" }) catch unreachable; + try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.body } }); + try stack.append(State{ .PointerIndexPayload = OptionalCtx{ .Optional = &node.payload } }); + try stack.append(State{ .ExpectToken = Token.Id.RParen }); + try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.array_expr } }); + try stack.append(State{ .ExpectToken = Token.Id.LParen }); continue; }, State.Else => |dest| { if (eatToken(&tok_it, &tree, Token.Id.Keyword_else)) |else_token| { - const node = try arena.construct(ast.Node.Else { - .base = ast.Node {.id = ast.Node.Id.Else }, + const node = try arena.construct(ast.Node.Else{ + .base = ast.Node{ .id = ast.Node.Id.Else }, .else_token = else_token, .payload = null, .body = undefined, }); - *dest = node; + dest.* = node; - stack.append(State { .Expression = OptionalCtx { .Required = &node.body } }) catch unreachable; - try stack.append(State { .Payload = OptionalCtx { .Optional = &node.payload } }); + stack.append(State{ .Expression = OptionalCtx{ .Required = &node.body } }) catch unreachable; + try stack.append(State{ .Payload = OptionalCtx{ .Optional = &node.payload } }); continue; } else { continue; } }, - State.Block => |block| { const token = nextToken(&tok_it, &tree); const token_index = token.index; @@ -1046,7 +955,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { }, else => { putBackToken(&tok_it, &tree); - stack.append(State { .Block = block }) catch unreachable; + stack.append(State{ .Block = block }) catch unreachable; var any_comments = false; while (try eatLineComment(arena, &tok_it, &tree)) |line_comment| { @@ -1055,7 +964,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { } if (any_comments) continue; - try stack.append(State { .Statement = block }); + try stack.append(State{ .Statement = block }); continue; }, } @@ -1066,33 +975,29 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { const token_ptr = token.ptr; switch (token_ptr.id) { Token.Id.Keyword_comptime => { - stack.append(State { - .ComptimeStatement = ComptimeStatementCtx { - .comptime_token = token_index, - .block = block, - } - }) catch unreachable; + stack.append(State{ .ComptimeStatement = ComptimeStatementCtx{ + .comptime_token = token_index, + .block = block, + } }) catch unreachable; continue; }, - Token.Id.Keyword_var, Token.Id.Keyword_const => { - stack.append(State { - .VarDecl = VarDeclCtx { - .comments = null, - .visib_token = null, - .comptime_token = null, - .extern_export_token = null, - .lib_name = null, - .mut_token = token_index, - .list = &block.statements, - } - }) catch unreachable; + Token.Id.Keyword_var, + Token.Id.Keyword_const => { + stack.append(State{ .VarDecl = VarDeclCtx{ + .comments = null, + .visib_token = null, + .comptime_token = null, + .extern_export_token = null, + .lib_name = null, + .mut_token = token_index, + .list = &block.statements, + } }) catch unreachable; continue; }, - Token.Id.Keyword_defer, Token.Id.Keyword_errdefer => { - const node = try arena.construct(ast.Node.Defer { - .base = ast.Node { - .id = ast.Node.Id.Defer, - }, + Token.Id.Keyword_defer, + Token.Id.Keyword_errdefer => { + const node = try arena.construct(ast.Node.Defer{ + .base = ast.Node{ .id = ast.Node.Id.Defer }, .defer_token = token_index, .kind = switch (token_ptr.id) { Token.Id.Keyword_defer => ast.Node.Defer.Kind.Unconditional, @@ -1102,15 +1007,15 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { .expr = undefined, }); const node_ptr = try block.statements.addOne(); - *node_ptr = &node.base; + node_ptr.* = &node.base; - stack.append(State { .Semicolon = node_ptr }) catch unreachable; - try stack.append(State { .AssignmentExpressionBegin = OptionalCtx{ .Required = &node.expr } }); + stack.append(State{ .Semicolon = node_ptr }) catch unreachable; + try stack.append(State{ .AssignmentExpressionBegin = OptionalCtx{ .Required = &node.expr } }); continue; }, Token.Id.LBrace => { - const inner_block = try arena.construct(ast.Node.Block { - .base = ast.Node { .id = ast.Node.Id.Block }, + const inner_block = try arena.construct(ast.Node.Block{ + .base = ast.Node{ .id = ast.Node.Id.Block }, .label = null, .lbrace = token_index, .statements = ast.Node.Block.StatementList.init(arena), @@ -1118,16 +1023,16 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { }); try block.statements.push(&inner_block.base); - stack.append(State { .Block = inner_block }) catch unreachable; + stack.append(State{ .Block = inner_block }) catch unreachable; continue; }, else => { putBackToken(&tok_it, &tree); const statement = try block.statements.addOne(); - try stack.append(State { .Semicolon = statement }); - try stack.append(State { .AssignmentExpressionBegin = OptionalCtx{ .Required = statement } }); + try stack.append(State{ .Semicolon = statement }); + try stack.append(State{ .AssignmentExpressionBegin = OptionalCtx{ .Required = statement } }); continue; - } + }, } }, State.ComptimeStatement => |ctx| { @@ -1135,34 +1040,33 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { const token_index = token.index; const token_ptr = token.ptr; switch (token_ptr.id) { - Token.Id.Keyword_var, Token.Id.Keyword_const => { - stack.append(State { - .VarDecl = VarDeclCtx { - .comments = null, - .visib_token = null, - .comptime_token = ctx.comptime_token, - .extern_export_token = null, - .lib_name = null, - .mut_token = token_index, - .list = &ctx.block.statements, - } - }) catch unreachable; + Token.Id.Keyword_var, + Token.Id.Keyword_const => { + stack.append(State{ .VarDecl = VarDeclCtx{ + .comments = null, + .visib_token = null, + .comptime_token = ctx.comptime_token, + .extern_export_token = null, + .lib_name = null, + .mut_token = token_index, + .list = &ctx.block.statements, + } }) catch unreachable; continue; }, else => { putBackToken(&tok_it, &tree); putBackToken(&tok_it, &tree); const statement = try ctx.block.statements.addOne(); - try stack.append(State { .Semicolon = statement }); - try stack.append(State { .Expression = OptionalCtx { .Required = statement } }); + try stack.append(State{ .Semicolon = statement }); + try stack.append(State{ .Expression = OptionalCtx{ .Required = statement } }); continue; - } + }, } }, State.Semicolon => |node_ptr| { - const node = *node_ptr; + const node = node_ptr.*; if (node.requireSemiColon()) { - stack.append(State { .ExpectToken = Token.Id.Semicolon }) catch unreachable; + stack.append(State{ .ExpectToken = Token.Id.Semicolon }) catch unreachable; continue; } continue; @@ -1177,22 +1081,22 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { continue; } - const node = try arena.construct(ast.Node.AsmOutput { - .base = ast.Node {.id = ast.Node.Id.AsmOutput }, + const node = try arena.construct(ast.Node.AsmOutput{ + .base = ast.Node{ .id = ast.Node.Id.AsmOutput }, .symbolic_name = undefined, .constraint = undefined, .kind = undefined, }); try items.push(node); - stack.append(State { .AsmOutputItems = items }) catch unreachable; - try stack.append(State { .IfToken = Token.Id.Comma }); - try stack.append(State { .ExpectToken = Token.Id.RParen }); - try stack.append(State { .AsmOutputReturnOrType = node }); - try stack.append(State { .ExpectToken = Token.Id.LParen }); - try stack.append(State { .StringLiteral = OptionalCtx { .Required = &node.constraint } }); - try stack.append(State { .ExpectToken = Token.Id.RBracket }); - try stack.append(State { .Identifier = OptionalCtx { .Required = &node.symbolic_name } }); + stack.append(State{ .AsmOutputItems = items }) catch unreachable; + try stack.append(State{ .IfToken = Token.Id.Comma }); + try stack.append(State{ .ExpectToken = Token.Id.RParen }); + try stack.append(State{ .AsmOutputReturnOrType = node }); + try stack.append(State{ .ExpectToken = Token.Id.LParen }); + try stack.append(State{ .StringLiteral = OptionalCtx{ .Required = &node.constraint } }); + try stack.append(State{ .ExpectToken = Token.Id.RBracket }); + try stack.append(State{ .Identifier = OptionalCtx{ .Required = &node.symbolic_name } }); continue; }, State.AsmOutputReturnOrType => |node| { @@ -1201,20 +1105,16 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { const token_ptr = token.ptr; switch (token_ptr.id) { Token.Id.Identifier => { - node.kind = ast.Node.AsmOutput.Kind { .Variable = try createLiteral(arena, ast.Node.Identifier, token_index) }; + node.kind = ast.Node.AsmOutput.Kind{ .Variable = try createLiteral(arena, ast.Node.Identifier, token_index) }; continue; }, Token.Id.Arrow => { - node.kind = ast.Node.AsmOutput.Kind { .Return = undefined }; - try stack.append(State { .TypeExprBegin = OptionalCtx { .Required = &node.kind.Return } }); + node.kind = ast.Node.AsmOutput.Kind{ .Return = undefined }; + try stack.append(State{ .TypeExprBegin = OptionalCtx{ .Required = &node.kind.Return } }); continue; }, else => { - *(try tree.errors.addOne()) = Error { - .ExpectedAsmOutputReturnOrType = Error.ExpectedAsmOutputReturnOrType { - .token = token_index, - }, - }; + ((try tree.errors.addOne())).* = Error{ .ExpectedAsmOutputReturnOrType = Error.ExpectedAsmOutputReturnOrType{ .token = token_index } }; return tree; }, } @@ -1228,49 +1128,48 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { continue; } - const node = try arena.construct(ast.Node.AsmInput { - .base = ast.Node {.id = ast.Node.Id.AsmInput }, + const node = try arena.construct(ast.Node.AsmInput{ + .base = ast.Node{ .id = ast.Node.Id.AsmInput }, .symbolic_name = undefined, .constraint = undefined, .expr = undefined, }); try items.push(node); - stack.append(State { .AsmInputItems = items }) catch unreachable; - try stack.append(State { .IfToken = Token.Id.Comma }); - try stack.append(State { .ExpectToken = Token.Id.RParen }); - try stack.append(State { .Expression = OptionalCtx { .Required = &node.expr } }); - try stack.append(State { .ExpectToken = Token.Id.LParen }); - try stack.append(State { .StringLiteral = OptionalCtx { .Required = &node.constraint } }); - try stack.append(State { .ExpectToken = Token.Id.RBracket }); - try stack.append(State { .Identifier = OptionalCtx { .Required = &node.symbolic_name } }); + stack.append(State{ .AsmInputItems = items }) catch unreachable; + try stack.append(State{ .IfToken = Token.Id.Comma }); + try stack.append(State{ .ExpectToken = Token.Id.RParen }); + try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.expr } }); + try stack.append(State{ .ExpectToken = Token.Id.LParen }); + try stack.append(State{ .StringLiteral = OptionalCtx{ .Required = &node.constraint } }); + try stack.append(State{ .ExpectToken = Token.Id.RBracket }); + try stack.append(State{ .Identifier = OptionalCtx{ .Required = &node.symbolic_name } }); continue; }, State.AsmClobberItems => |items| { - stack.append(State { .AsmClobberItems = items }) catch unreachable; - try stack.append(State { .IfToken = Token.Id.Comma }); - try stack.append(State { .StringLiteral = OptionalCtx { .Required = try items.addOne() } }); + stack.append(State{ .AsmClobberItems = items }) catch unreachable; + try stack.append(State{ .IfToken = Token.Id.Comma }); + try stack.append(State{ .StringLiteral = OptionalCtx{ .Required = try items.addOne() } }); continue; }, - State.ExprListItemOrEnd => |list_state| { if (eatToken(&tok_it, &tree, list_state.end)) |token_index| { - *list_state.ptr = token_index; + (list_state.ptr).* = token_index; continue; } - stack.append(State { .ExprListCommaOrEnd = list_state }) catch unreachable; - try stack.append(State { .Expression = OptionalCtx { .Required = try list_state.list.addOne() } }); + stack.append(State{ .ExprListCommaOrEnd = list_state }) catch unreachable; + try stack.append(State{ .Expression = OptionalCtx{ .Required = try list_state.list.addOne() } }); continue; }, State.ExprListCommaOrEnd => |list_state| { switch (expectCommaOrEnd(&tok_it, &tree, list_state.end)) { ExpectCommaOrEndResult.end_token => |maybe_end| if (maybe_end) |end| { - *list_state.ptr = end; + (list_state.ptr).* = end; continue; } else { - stack.append(State { .ExprListItemOrEnd = list_state }) catch unreachable; + stack.append(State{ .ExprListItemOrEnd = list_state }) catch unreachable; continue; }, ExpectCommaOrEndResult.parse_error => |e| { @@ -1285,44 +1184,38 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { } if (eatToken(&tok_it, &tree, Token.Id.RBrace)) |rbrace| { - *list_state.ptr = rbrace; + (list_state.ptr).* = rbrace; continue; } - const node = try arena.construct(ast.Node.FieldInitializer { - .base = ast.Node { - .id = ast.Node.Id.FieldInitializer, - }, + const node = try arena.construct(ast.Node.FieldInitializer{ + .base = ast.Node{ .id = ast.Node.Id.FieldInitializer }, .period_token = undefined, .name_token = undefined, .expr = undefined, }); try list_state.list.push(&node.base); - stack.append(State { .FieldInitListCommaOrEnd = list_state }) catch unreachable; - try stack.append(State { .Expression = OptionalCtx{ .Required = &node.expr } }); - try stack.append(State { .ExpectToken = Token.Id.Equal }); - try stack.append(State { - .ExpectTokenSave = ExpectTokenSave { - .id = Token.Id.Identifier, - .ptr = &node.name_token, - } - }); - try stack.append(State { - .ExpectTokenSave = ExpectTokenSave { - .id = Token.Id.Period, - .ptr = &node.period_token, - } - }); + stack.append(State{ .FieldInitListCommaOrEnd = list_state }) catch unreachable; + try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.expr } }); + try stack.append(State{ .ExpectToken = Token.Id.Equal }); + try stack.append(State{ .ExpectTokenSave = ExpectTokenSave{ + .id = Token.Id.Identifier, + .ptr = &node.name_token, + } }); + try stack.append(State{ .ExpectTokenSave = ExpectTokenSave{ + .id = Token.Id.Period, + .ptr = &node.period_token, + } }); continue; }, State.FieldInitListCommaOrEnd => |list_state| { switch (expectCommaOrEnd(&tok_it, &tree, Token.Id.RBrace)) { ExpectCommaOrEndResult.end_token => |maybe_end| if (maybe_end) |end| { - *list_state.ptr = end; + (list_state.ptr).* = end; continue; } else { - stack.append(State { .FieldInitListItemOrEnd = list_state }) catch unreachable; + stack.append(State{ .FieldInitListItemOrEnd = list_state }) catch unreachable; continue; }, ExpectCommaOrEndResult.parse_error => |e| { @@ -1337,7 +1230,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { container_decl.rbrace_token = end; continue; } else { - try stack.append(State { .ContainerDecl = container_decl }); + try stack.append(State{ .ContainerDecl = container_decl }); continue; }, ExpectCommaOrEndResult.parse_error => |e| { @@ -1352,23 +1245,23 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { } if (eatToken(&tok_it, &tree, Token.Id.RBrace)) |rbrace| { - *list_state.ptr = rbrace; + (list_state.ptr).* = rbrace; continue; } const node_ptr = try list_state.list.addOne(); - try stack.append(State { .ErrorTagListCommaOrEnd = list_state }); - try stack.append(State { .ErrorTag = node_ptr }); + try stack.append(State{ .ErrorTagListCommaOrEnd = list_state }); + try stack.append(State{ .ErrorTag = node_ptr }); continue; }, State.ErrorTagListCommaOrEnd => |list_state| { switch (expectCommaOrEnd(&tok_it, &tree, Token.Id.RBrace)) { ExpectCommaOrEndResult.end_token => |maybe_end| if (maybe_end) |end| { - *list_state.ptr = end; + (list_state.ptr).* = end; continue; } else { - stack.append(State { .ErrorTagListItemOrEnd = list_state }) catch unreachable; + stack.append(State{ .ErrorTagListItemOrEnd = list_state }) catch unreachable; continue; }, ExpectCommaOrEndResult.parse_error => |e| { @@ -1383,24 +1276,22 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { } if (eatToken(&tok_it, &tree, Token.Id.RBrace)) |rbrace| { - *list_state.ptr = rbrace; + (list_state.ptr).* = rbrace; continue; } const comments = try eatDocComments(arena, &tok_it, &tree); - const node = try arena.construct(ast.Node.SwitchCase { - .base = ast.Node { - .id = ast.Node.Id.SwitchCase, - }, + const node = try arena.construct(ast.Node.SwitchCase{ + .base = ast.Node{ .id = ast.Node.Id.SwitchCase }, .items = ast.Node.SwitchCase.ItemList.init(arena), .payload = null, .expr = undefined, }); try list_state.list.push(&node.base); - try stack.append(State { .SwitchCaseCommaOrEnd = list_state }); - try stack.append(State { .AssignmentExpressionBegin = OptionalCtx { .Required = &node.expr } }); - try stack.append(State { .PointerPayload = OptionalCtx { .Optional = &node.payload } }); - try stack.append(State { .SwitchCaseFirstItem = &node.items }); + try stack.append(State{ .SwitchCaseCommaOrEnd = list_state }); + try stack.append(State{ .AssignmentExpressionBegin = OptionalCtx{ .Required = &node.expr } }); + try stack.append(State{ .PointerPayload = OptionalCtx{ .Optional = &node.payload } }); + try stack.append(State{ .SwitchCaseFirstItem = &node.items }); continue; }, @@ -1408,10 +1299,10 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { State.SwitchCaseCommaOrEnd => |list_state| { switch (expectCommaOrEnd(&tok_it, &tree, Token.Id.RParen)) { ExpectCommaOrEndResult.end_token => |maybe_end| if (maybe_end) |end| { - *list_state.ptr = end; + (list_state.ptr).* = end; continue; } else { - try stack.append(State { .SwitchCaseOrEnd = list_state }); + try stack.append(State{ .SwitchCaseOrEnd = list_state }); continue; }, ExpectCommaOrEndResult.parse_error => |e| { @@ -1426,29 +1317,29 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { const token_index = token.index; const token_ptr = token.ptr; if (token_ptr.id == Token.Id.Keyword_else) { - const else_node = try arena.construct(ast.Node.SwitchElse { - .base = ast.Node{ .id = ast.Node.Id.SwitchElse}, + const else_node = try arena.construct(ast.Node.SwitchElse{ + .base = ast.Node{ .id = ast.Node.Id.SwitchElse }, .token = token_index, }); try case_items.push(&else_node.base); - try stack.append(State { .ExpectToken = Token.Id.EqualAngleBracketRight }); + try stack.append(State{ .ExpectToken = Token.Id.EqualAngleBracketRight }); continue; } else { putBackToken(&tok_it, &tree); - try stack.append(State { .SwitchCaseItem = case_items }); + try stack.append(State{ .SwitchCaseItem = case_items }); continue; } }, State.SwitchCaseItem => |case_items| { - stack.append(State { .SwitchCaseItemCommaOrEnd = case_items }) catch unreachable; - try stack.append(State { .RangeExpressionBegin = OptionalCtx { .Required = try case_items.addOne() } }); + stack.append(State{ .SwitchCaseItemCommaOrEnd = case_items }) catch unreachable; + try stack.append(State{ .RangeExpressionBegin = OptionalCtx{ .Required = try case_items.addOne() } }); }, State.SwitchCaseItemCommaOrEnd => |case_items| { switch (expectCommaOrEnd(&tok_it, &tree, Token.Id.EqualAngleBracketRight)) { ExpectCommaOrEndResult.end_token => |t| { if (t == null) { - stack.append(State { .SwitchCaseItem = case_items }) catch unreachable; + stack.append(State{ .SwitchCaseItem = case_items }) catch unreachable; } continue; }, @@ -1460,10 +1351,9 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { continue; }, - State.SuspendBody => |suspend_node| { if (suspend_node.payload != null) { - try stack.append(State { .AssignmentExpressionBegin = OptionalCtx { .RequiredNull = &suspend_node.body } }); + try stack.append(State{ .AssignmentExpressionBegin = OptionalCtx{ .RequiredNull = &suspend_node.body } }); } continue; }, @@ -1473,13 +1363,11 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { } async_node.rangle_bracket = TokenIndex(0); - try stack.append(State { - .ExpectTokenSave = ExpectTokenSave { - .id = Token.Id.AngleBracketRight, - .ptr = &??async_node.rangle_bracket, - } - }); - try stack.append(State { .TypeExprBegin = OptionalCtx { .RequiredNull = &async_node.allocator_type } }); + try stack.append(State{ .ExpectTokenSave = ExpectTokenSave{ + .id = Token.Id.AngleBracketRight, + .ptr = &??async_node.rangle_bracket, + } }); + try stack.append(State{ .TypeExprBegin = OptionalCtx{ .RequiredNull = &async_node.allocator_type } }); continue; }, State.AsyncEnd => |ctx| { @@ -1498,27 +1386,20 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { continue; } - *(try tree.errors.addOne()) = Error { - .ExpectedCall = Error.ExpectedCall { .node = node }, - }; + ((try tree.errors.addOne())).* = Error{ .ExpectedCall = Error.ExpectedCall{ .node = node } }; return tree; }, else => { - *(try tree.errors.addOne()) = Error { - .ExpectedCallOrFnProto = Error.ExpectedCallOrFnProto { .node = node }, - }; + ((try tree.errors.addOne())).* = Error{ .ExpectedCallOrFnProto = Error.ExpectedCallOrFnProto{ .node = node } }; return tree; - } + }, } }, - State.ExternType => |ctx| { if (eatToken(&tok_it, &tree, Token.Id.Keyword_fn)) |fn_token| { - const fn_proto = try arena.construct(ast.Node.FnProto { - .base = ast.Node { - .id = ast.Node.Id.FnProto, - }, + const fn_proto = try arena.construct(ast.Node.FnProto{ + .base = ast.Node{ .id = ast.Node.Id.FnProto }, .doc_comments = ctx.comments, .visib_token = null, .name_token = null, @@ -1534,17 +1415,15 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { .align_expr = null, }); ctx.opt_ctx.store(&fn_proto.base); - stack.append(State { .FnProto = fn_proto }) catch unreachable; + stack.append(State{ .FnProto = fn_proto }) catch unreachable; continue; } - stack.append(State { - .ContainerKind = ContainerKindCtx { - .opt_ctx = ctx.opt_ctx, - .ltoken = ctx.extern_token, - .layout = ast.Node.ContainerDecl.Layout.Extern, - }, - }) catch unreachable; + stack.append(State{ .ContainerKind = ContainerKindCtx{ + .opt_ctx = ctx.opt_ctx, + .ltoken = ctx.extern_token, + .layout = ast.Node.ContainerDecl.Layout.Extern, + } }) catch unreachable; continue; }, State.SliceOrArrayAccess => |node| { @@ -1554,20 +1433,16 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { switch (token_ptr.id) { Token.Id.Ellipsis2 => { const start = node.op.ArrayAccess; - node.op = ast.Node.SuffixOp.Op { - .Slice = ast.Node.SuffixOp.Op.Slice { - .start = start, - .end = null, - } - }; + node.op = ast.Node.SuffixOp.Op{ .Slice = ast.Node.SuffixOp.Op.Slice{ + .start = start, + .end = null, + } }; - stack.append(State { - .ExpectTokenSave = ExpectTokenSave { - .id = Token.Id.RBracket, - .ptr = &node.rtoken, - } - }) catch unreachable; - try stack.append(State { .Expression = OptionalCtx { .Optional = &node.op.Slice.end } }); + stack.append(State{ .ExpectTokenSave = ExpectTokenSave{ + .id = Token.Id.RBracket, + .ptr = &node.rtoken, + } }) catch unreachable; + try stack.append(State{ .Expression = OptionalCtx{ .Optional = &node.op.Slice.end } }); continue; }, Token.Id.RBracket => { @@ -1575,33 +1450,29 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { continue; }, else => { - *(try tree.errors.addOne()) = Error { - .ExpectedSliceOrRBracket = Error.ExpectedSliceOrRBracket { .token = token_index }, - }; + ((try tree.errors.addOne())).* = Error{ .ExpectedSliceOrRBracket = Error.ExpectedSliceOrRBracket{ .token = token_index } }; return tree; - } + }, } }, State.SliceOrArrayType => |node| { if (eatToken(&tok_it, &tree, Token.Id.RBracket)) |_| { - node.op = ast.Node.PrefixOp.Op { - .SliceType = ast.Node.PrefixOp.AddrOfInfo { - .align_expr = null, - .bit_offset_start_token = null, - .bit_offset_end_token = null, - .const_token = null, - .volatile_token = null, - } - }; - stack.append(State { .TypeExprBegin = OptionalCtx { .Required = &node.rhs } }) catch unreachable; - try stack.append(State { .AddrOfModifiers = &node.op.SliceType }); + node.op = ast.Node.PrefixOp.Op{ .SliceType = ast.Node.PrefixOp.AddrOfInfo{ + .align_expr = null, + .bit_offset_start_token = null, + .bit_offset_end_token = null, + .const_token = null, + .volatile_token = null, + } }; + stack.append(State{ .TypeExprBegin = OptionalCtx{ .Required = &node.rhs } }) catch unreachable; + try stack.append(State{ .AddrOfModifiers = &node.op.SliceType }); continue; } - node.op = ast.Node.PrefixOp.Op { .ArrayType = undefined }; - stack.append(State { .TypeExprBegin = OptionalCtx { .Required = &node.rhs } }) catch unreachable; - try stack.append(State { .ExpectToken = Token.Id.RBracket }); - try stack.append(State { .Expression = OptionalCtx { .Required = &node.op.ArrayType } }); + node.op = ast.Node.PrefixOp.Op{ .ArrayType = undefined }; + stack.append(State{ .TypeExprBegin = OptionalCtx{ .Required = &node.rhs } }) catch unreachable; + try stack.append(State{ .ExpectToken = Token.Id.RBracket }); + try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.op.ArrayType } }); continue; }, State.AddrOfModifiers => |addr_of_info| { @@ -1612,22 +1483,18 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { Token.Id.Keyword_align => { stack.append(state) catch unreachable; if (addr_of_info.align_expr != null) { - *(try tree.errors.addOne()) = Error { - .ExtraAlignQualifier = Error.ExtraAlignQualifier { .token = token_index }, - }; + ((try tree.errors.addOne())).* = Error{ .ExtraAlignQualifier = Error.ExtraAlignQualifier{ .token = token_index } }; return tree; } - try stack.append(State { .ExpectToken = Token.Id.RParen }); - try stack.append(State { .Expression = OptionalCtx { .RequiredNull = &addr_of_info.align_expr} }); - try stack.append(State { .ExpectToken = Token.Id.LParen }); + try stack.append(State{ .ExpectToken = Token.Id.RParen }); + try stack.append(State{ .Expression = OptionalCtx{ .RequiredNull = &addr_of_info.align_expr } }); + try stack.append(State{ .ExpectToken = Token.Id.LParen }); continue; }, Token.Id.Keyword_const => { stack.append(state) catch unreachable; if (addr_of_info.const_token != null) { - *(try tree.errors.addOne()) = Error { - .ExtraConstQualifier = Error.ExtraConstQualifier { .token = token_index }, - }; + ((try tree.errors.addOne())).* = Error{ .ExtraConstQualifier = Error.ExtraConstQualifier{ .token = token_index } }; return tree; } addr_of_info.const_token = token_index; @@ -1636,9 +1503,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { Token.Id.Keyword_volatile => { stack.append(state) catch unreachable; if (addr_of_info.volatile_token != null) { - *(try tree.errors.addOne()) = Error { - .ExtraVolatileQualifier = Error.ExtraVolatileQualifier { .token = token_index }, - }; + ((try tree.errors.addOne())).* = Error{ .ExtraVolatileQualifier = Error.ExtraVolatileQualifier{ .token = token_index } }; return tree; } addr_of_info.volatile_token = token_index; @@ -1651,19 +1516,16 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { } }, - State.Payload => |opt_ctx| { const token = nextToken(&tok_it, &tree); const token_index = token.index; const token_ptr = token.ptr; if (token_ptr.id != Token.Id.Pipe) { if (opt_ctx != OptionalCtx.Optional) { - *(try tree.errors.addOne()) = Error { - .ExpectedToken = Error.ExpectedToken { - .token = token_index, - .expected_id = Token.Id.Pipe, - }, - }; + ((try tree.errors.addOne())).* = Error{ .ExpectedToken = Error.ExpectedToken{ + .token = token_index, + .expected_id = Token.Id.Pipe, + } }; return tree; } @@ -1671,21 +1533,19 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { continue; } - const node = try arena.construct(ast.Node.Payload { - .base = ast.Node {.id = ast.Node.Id.Payload }, + const node = try arena.construct(ast.Node.Payload{ + .base = ast.Node{ .id = ast.Node.Id.Payload }, .lpipe = token_index, .error_symbol = undefined, - .rpipe = undefined + .rpipe = undefined, }); opt_ctx.store(&node.base); - stack.append(State { - .ExpectTokenSave = ExpectTokenSave { - .id = Token.Id.Pipe, - .ptr = &node.rpipe, - } - }) catch unreachable; - try stack.append(State { .Identifier = OptionalCtx { .Required = &node.error_symbol } }); + stack.append(State{ .ExpectTokenSave = ExpectTokenSave{ + .id = Token.Id.Pipe, + .ptr = &node.rpipe, + } }) catch unreachable; + try stack.append(State{ .Identifier = OptionalCtx{ .Required = &node.error_symbol } }); continue; }, State.PointerPayload => |opt_ctx| { @@ -1694,12 +1554,10 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { const token_ptr = token.ptr; if (token_ptr.id != Token.Id.Pipe) { if (opt_ctx != OptionalCtx.Optional) { - *(try tree.errors.addOne()) = Error { - .ExpectedToken = Error.ExpectedToken { - .token = token_index, - .expected_id = Token.Id.Pipe, - }, - }; + ((try tree.errors.addOne())).* = Error{ .ExpectedToken = Error.ExpectedToken{ + .token = token_index, + .expected_id = Token.Id.Pipe, + } }; return tree; } @@ -1707,28 +1565,24 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { continue; } - const node = try arena.construct(ast.Node.PointerPayload { - .base = ast.Node {.id = ast.Node.Id.PointerPayload }, + const node = try arena.construct(ast.Node.PointerPayload{ + .base = ast.Node{ .id = ast.Node.Id.PointerPayload }, .lpipe = token_index, .ptr_token = null, .value_symbol = undefined, - .rpipe = undefined + .rpipe = undefined, }); opt_ctx.store(&node.base); - try stack.append(State { - .ExpectTokenSave = ExpectTokenSave { - .id = Token.Id.Pipe, - .ptr = &node.rpipe, - } - }); - try stack.append(State { .Identifier = OptionalCtx { .Required = &node.value_symbol } }); - try stack.append(State { - .OptionalTokenSave = OptionalTokenSave { - .id = Token.Id.Asterisk, - .ptr = &node.ptr_token, - } - }); + try stack.append(State{ .ExpectTokenSave = ExpectTokenSave{ + .id = Token.Id.Pipe, + .ptr = &node.rpipe, + } }); + try stack.append(State{ .Identifier = OptionalCtx{ .Required = &node.value_symbol } }); + try stack.append(State{ .OptionalTokenSave = OptionalTokenSave{ + .id = Token.Id.Asterisk, + .ptr = &node.ptr_token, + } }); continue; }, State.PointerIndexPayload => |opt_ctx| { @@ -1737,12 +1591,10 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { const token_ptr = token.ptr; if (token_ptr.id != Token.Id.Pipe) { if (opt_ctx != OptionalCtx.Optional) { - *(try tree.errors.addOne()) = Error { - .ExpectedToken = Error.ExpectedToken { - .token = token_index, - .expected_id = Token.Id.Pipe, - }, - }; + ((try tree.errors.addOne())).* = Error{ .ExpectedToken = Error.ExpectedToken{ + .token = token_index, + .expected_id = Token.Id.Pipe, + } }; return tree; } @@ -1750,61 +1602,58 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { continue; } - const node = try arena.construct(ast.Node.PointerIndexPayload { - .base = ast.Node {.id = ast.Node.Id.PointerIndexPayload }, + const node = try arena.construct(ast.Node.PointerIndexPayload{ + .base = ast.Node{ .id = ast.Node.Id.PointerIndexPayload }, .lpipe = token_index, .ptr_token = null, .value_symbol = undefined, .index_symbol = null, - .rpipe = undefined + .rpipe = undefined, }); opt_ctx.store(&node.base); - stack.append(State { - .ExpectTokenSave = ExpectTokenSave { - .id = Token.Id.Pipe, - .ptr = &node.rpipe, - } - }) catch unreachable; - try stack.append(State { .Identifier = OptionalCtx { .RequiredNull = &node.index_symbol } }); - try stack.append(State { .IfToken = Token.Id.Comma }); - try stack.append(State { .Identifier = OptionalCtx { .Required = &node.value_symbol } }); - try stack.append(State { - .OptionalTokenSave = OptionalTokenSave { - .id = Token.Id.Asterisk, - .ptr = &node.ptr_token, - } - }); + stack.append(State{ .ExpectTokenSave = ExpectTokenSave{ + .id = Token.Id.Pipe, + .ptr = &node.rpipe, + } }) catch unreachable; + try stack.append(State{ .Identifier = OptionalCtx{ .RequiredNull = &node.index_symbol } }); + try stack.append(State{ .IfToken = Token.Id.Comma }); + try stack.append(State{ .Identifier = OptionalCtx{ .Required = &node.value_symbol } }); + try stack.append(State{ .OptionalTokenSave = OptionalTokenSave{ + .id = Token.Id.Asterisk, + .ptr = &node.ptr_token, + } }); continue; }, - State.Expression => |opt_ctx| { const token = nextToken(&tok_it, &tree); const token_index = token.index; const token_ptr = token.ptr; switch (token_ptr.id) { - Token.Id.Keyword_return, Token.Id.Keyword_break, Token.Id.Keyword_continue => { - const node = try arena.construct(ast.Node.ControlFlowExpression { - .base = ast.Node {.id = ast.Node.Id.ControlFlowExpression }, + Token.Id.Keyword_return, + Token.Id.Keyword_break, + Token.Id.Keyword_continue => { + const node = try arena.construct(ast.Node.ControlFlowExpression{ + .base = ast.Node{ .id = ast.Node.Id.ControlFlowExpression }, .ltoken = token_index, .kind = undefined, .rhs = null, }); opt_ctx.store(&node.base); - stack.append(State { .Expression = OptionalCtx { .Optional = &node.rhs } }) catch unreachable; + stack.append(State{ .Expression = OptionalCtx{ .Optional = &node.rhs } }) catch unreachable; switch (token_ptr.id) { Token.Id.Keyword_break => { - node.kind = ast.Node.ControlFlowExpression.Kind { .Break = null }; - try stack.append(State { .Identifier = OptionalCtx { .RequiredNull = &node.kind.Break } }); - try stack.append(State { .IfToken = Token.Id.Colon }); + node.kind = ast.Node.ControlFlowExpression.Kind{ .Break = null }; + try stack.append(State{ .Identifier = OptionalCtx{ .RequiredNull = &node.kind.Break } }); + try stack.append(State{ .IfToken = Token.Id.Colon }); }, Token.Id.Keyword_continue => { - node.kind = ast.Node.ControlFlowExpression.Kind { .Continue = null }; - try stack.append(State { .Identifier = OptionalCtx { .RequiredNull = &node.kind.Continue } }); - try stack.append(State { .IfToken = Token.Id.Colon }); + node.kind = ast.Node.ControlFlowExpression.Kind{ .Continue = null }; + try stack.append(State{ .Identifier = OptionalCtx{ .RequiredNull = &node.kind.Continue } }); + try stack.append(State{ .IfToken = Token.Id.Colon }); }, Token.Id.Keyword_return => { node.kind = ast.Node.ControlFlowExpression.Kind.Return; @@ -1813,56 +1662,58 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { } continue; }, - Token.Id.Keyword_try, Token.Id.Keyword_cancel, Token.Id.Keyword_resume => { - const node = try arena.construct(ast.Node.PrefixOp { - .base = ast.Node {.id = ast.Node.Id.PrefixOp }, + Token.Id.Keyword_try, + Token.Id.Keyword_cancel, + Token.Id.Keyword_resume => { + const node = try arena.construct(ast.Node.PrefixOp{ + .base = ast.Node{ .id = ast.Node.Id.PrefixOp }, .op_token = token_index, .op = switch (token_ptr.id) { - Token.Id.Keyword_try => ast.Node.PrefixOp.Op { .Try = void{} }, - Token.Id.Keyword_cancel => ast.Node.PrefixOp.Op { .Cancel = void{} }, - Token.Id.Keyword_resume => ast.Node.PrefixOp.Op { .Resume = void{} }, + Token.Id.Keyword_try => ast.Node.PrefixOp.Op{ .Try = void{} }, + Token.Id.Keyword_cancel => ast.Node.PrefixOp.Op{ .Cancel = void{} }, + Token.Id.Keyword_resume => ast.Node.PrefixOp.Op{ .Resume = void{} }, else => unreachable, }, .rhs = undefined, }); opt_ctx.store(&node.base); - stack.append(State { .Expression = OptionalCtx { .Required = &node.rhs } }) catch unreachable; + stack.append(State{ .Expression = OptionalCtx{ .Required = &node.rhs } }) catch unreachable; continue; }, else => { if (!try parseBlockExpr(&stack, arena, opt_ctx, token_ptr, token_index)) { putBackToken(&tok_it, &tree); - stack.append(State { .UnwrapExpressionBegin = opt_ctx }) catch unreachable; + stack.append(State{ .UnwrapExpressionBegin = opt_ctx }) catch unreachable; } continue; - } + }, } }, State.RangeExpressionBegin => |opt_ctx| { - stack.append(State { .RangeExpressionEnd = opt_ctx }) catch unreachable; - try stack.append(State { .Expression = opt_ctx }); + stack.append(State{ .RangeExpressionEnd = opt_ctx }) catch unreachable; + try stack.append(State{ .Expression = opt_ctx }); continue; }, State.RangeExpressionEnd => |opt_ctx| { const lhs = opt_ctx.get() ?? continue; if (eatToken(&tok_it, &tree, Token.Id.Ellipsis3)) |ellipsis3| { - const node = try arena.construct(ast.Node.InfixOp { - .base = ast.Node {.id = ast.Node.Id.InfixOp }, + const node = try arena.construct(ast.Node.InfixOp{ + .base = ast.Node{ .id = ast.Node.Id.InfixOp }, .lhs = lhs, .op_token = ellipsis3, .op = ast.Node.InfixOp.Op.Range, .rhs = undefined, }); opt_ctx.store(&node.base); - stack.append(State { .Expression = OptionalCtx { .Required = &node.rhs } }) catch unreachable; + stack.append(State{ .Expression = OptionalCtx{ .Required = &node.rhs } }) catch unreachable; continue; } }, State.AssignmentExpressionBegin => |opt_ctx| { - stack.append(State { .AssignmentExpressionEnd = opt_ctx }) catch unreachable; - try stack.append(State { .Expression = opt_ctx }); + stack.append(State{ .AssignmentExpressionEnd = opt_ctx }) catch unreachable; + try stack.append(State{ .Expression = opt_ctx }); continue; }, @@ -1873,16 +1724,16 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { const token_index = token.index; const token_ptr = token.ptr; if (tokenIdToAssignment(token_ptr.id)) |ass_id| { - const node = try arena.construct(ast.Node.InfixOp { - .base = ast.Node {.id = ast.Node.Id.InfixOp }, + const node = try arena.construct(ast.Node.InfixOp{ + .base = ast.Node{ .id = ast.Node.Id.InfixOp }, .lhs = lhs, .op_token = token_index, .op = ass_id, .rhs = undefined, }); opt_ctx.store(&node.base); - stack.append(State { .AssignmentExpressionEnd = opt_ctx.toRequired() }) catch unreachable; - try stack.append(State { .Expression = OptionalCtx { .Required = &node.rhs } }); + stack.append(State{ .AssignmentExpressionEnd = opt_ctx.toRequired() }) catch unreachable; + try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.rhs } }); continue; } else { putBackToken(&tok_it, &tree); @@ -1891,8 +1742,8 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { }, State.UnwrapExpressionBegin => |opt_ctx| { - stack.append(State { .UnwrapExpressionEnd = opt_ctx }) catch unreachable; - try stack.append(State { .BoolOrExpressionBegin = opt_ctx }); + stack.append(State{ .UnwrapExpressionEnd = opt_ctx }) catch unreachable; + try stack.append(State{ .BoolOrExpressionBegin = opt_ctx }); continue; }, @@ -1903,8 +1754,8 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { const token_index = token.index; const token_ptr = token.ptr; if (tokenIdToUnwrapExpr(token_ptr.id)) |unwrap_id| { - const node = try arena.construct(ast.Node.InfixOp { - .base = ast.Node {.id = ast.Node.Id.InfixOp }, + const node = try arena.construct(ast.Node.InfixOp{ + .base = ast.Node{ .id = ast.Node.Id.InfixOp }, .lhs = lhs, .op_token = token_index, .op = unwrap_id, @@ -1912,11 +1763,11 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { }); opt_ctx.store(&node.base); - stack.append(State { .UnwrapExpressionEnd = opt_ctx.toRequired() }) catch unreachable; - try stack.append(State { .Expression = OptionalCtx { .Required = &node.rhs } }); + stack.append(State{ .UnwrapExpressionEnd = opt_ctx.toRequired() }) catch unreachable; + try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.rhs } }); if (node.op == ast.Node.InfixOp.Op.Catch) { - try stack.append(State { .Payload = OptionalCtx { .Optional = &node.op.Catch } }); + try stack.append(State{ .Payload = OptionalCtx{ .Optional = &node.op.Catch } }); } continue; } else { @@ -1926,8 +1777,8 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { }, State.BoolOrExpressionBegin => |opt_ctx| { - stack.append(State { .BoolOrExpressionEnd = opt_ctx }) catch unreachable; - try stack.append(State { .BoolAndExpressionBegin = opt_ctx }); + stack.append(State{ .BoolOrExpressionEnd = opt_ctx }) catch unreachable; + try stack.append(State{ .BoolAndExpressionBegin = opt_ctx }); continue; }, @@ -1935,23 +1786,23 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { const lhs = opt_ctx.get() ?? continue; if (eatToken(&tok_it, &tree, Token.Id.Keyword_or)) |or_token| { - const node = try arena.construct(ast.Node.InfixOp { - .base = ast.Node {.id = ast.Node.Id.InfixOp }, + const node = try arena.construct(ast.Node.InfixOp{ + .base = ast.Node{ .id = ast.Node.Id.InfixOp }, .lhs = lhs, .op_token = or_token, .op = ast.Node.InfixOp.Op.BoolOr, .rhs = undefined, }); opt_ctx.store(&node.base); - stack.append(State { .BoolOrExpressionEnd = opt_ctx.toRequired() }) catch unreachable; - try stack.append(State { .BoolAndExpressionBegin = OptionalCtx { .Required = &node.rhs } }); + stack.append(State{ .BoolOrExpressionEnd = opt_ctx.toRequired() }) catch unreachable; + try stack.append(State{ .BoolAndExpressionBegin = OptionalCtx{ .Required = &node.rhs } }); continue; } }, State.BoolAndExpressionBegin => |opt_ctx| { - stack.append(State { .BoolAndExpressionEnd = opt_ctx }) catch unreachable; - try stack.append(State { .ComparisonExpressionBegin = opt_ctx }); + stack.append(State{ .BoolAndExpressionEnd = opt_ctx }) catch unreachable; + try stack.append(State{ .ComparisonExpressionBegin = opt_ctx }); continue; }, @@ -1959,23 +1810,23 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { const lhs = opt_ctx.get() ?? continue; if (eatToken(&tok_it, &tree, Token.Id.Keyword_and)) |and_token| { - const node = try arena.construct(ast.Node.InfixOp { - .base = ast.Node {.id = ast.Node.Id.InfixOp }, + const node = try arena.construct(ast.Node.InfixOp{ + .base = ast.Node{ .id = ast.Node.Id.InfixOp }, .lhs = lhs, .op_token = and_token, .op = ast.Node.InfixOp.Op.BoolAnd, .rhs = undefined, }); opt_ctx.store(&node.base); - stack.append(State { .BoolAndExpressionEnd = opt_ctx.toRequired() }) catch unreachable; - try stack.append(State { .ComparisonExpressionBegin = OptionalCtx { .Required = &node.rhs } }); + stack.append(State{ .BoolAndExpressionEnd = opt_ctx.toRequired() }) catch unreachable; + try stack.append(State{ .ComparisonExpressionBegin = OptionalCtx{ .Required = &node.rhs } }); continue; } }, State.ComparisonExpressionBegin => |opt_ctx| { - stack.append(State { .ComparisonExpressionEnd = opt_ctx }) catch unreachable; - try stack.append(State { .BinaryOrExpressionBegin = opt_ctx }); + stack.append(State{ .ComparisonExpressionEnd = opt_ctx }) catch unreachable; + try stack.append(State{ .BinaryOrExpressionBegin = opt_ctx }); continue; }, @@ -1986,16 +1837,16 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { const token_index = token.index; const token_ptr = token.ptr; if (tokenIdToComparison(token_ptr.id)) |comp_id| { - const node = try arena.construct(ast.Node.InfixOp { - .base = ast.Node {.id = ast.Node.Id.InfixOp }, + const node = try arena.construct(ast.Node.InfixOp{ + .base = ast.Node{ .id = ast.Node.Id.InfixOp }, .lhs = lhs, .op_token = token_index, .op = comp_id, .rhs = undefined, }); opt_ctx.store(&node.base); - stack.append(State { .ComparisonExpressionEnd = opt_ctx.toRequired() }) catch unreachable; - try stack.append(State { .BinaryOrExpressionBegin = OptionalCtx { .Required = &node.rhs } }); + stack.append(State{ .ComparisonExpressionEnd = opt_ctx.toRequired() }) catch unreachable; + try stack.append(State{ .BinaryOrExpressionBegin = OptionalCtx{ .Required = &node.rhs } }); continue; } else { putBackToken(&tok_it, &tree); @@ -2004,8 +1855,8 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { }, State.BinaryOrExpressionBegin => |opt_ctx| { - stack.append(State { .BinaryOrExpressionEnd = opt_ctx }) catch unreachable; - try stack.append(State { .BinaryXorExpressionBegin = opt_ctx }); + stack.append(State{ .BinaryOrExpressionEnd = opt_ctx }) catch unreachable; + try stack.append(State{ .BinaryXorExpressionBegin = opt_ctx }); continue; }, @@ -2013,23 +1864,23 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { const lhs = opt_ctx.get() ?? continue; if (eatToken(&tok_it, &tree, Token.Id.Pipe)) |pipe| { - const node = try arena.construct(ast.Node.InfixOp { - .base = ast.Node {.id = ast.Node.Id.InfixOp }, + const node = try arena.construct(ast.Node.InfixOp{ + .base = ast.Node{ .id = ast.Node.Id.InfixOp }, .lhs = lhs, .op_token = pipe, .op = ast.Node.InfixOp.Op.BitOr, .rhs = undefined, }); opt_ctx.store(&node.base); - stack.append(State { .BinaryOrExpressionEnd = opt_ctx.toRequired() }) catch unreachable; - try stack.append(State { .BinaryXorExpressionBegin = OptionalCtx { .Required = &node.rhs } }); + stack.append(State{ .BinaryOrExpressionEnd = opt_ctx.toRequired() }) catch unreachable; + try stack.append(State{ .BinaryXorExpressionBegin = OptionalCtx{ .Required = &node.rhs } }); continue; } }, State.BinaryXorExpressionBegin => |opt_ctx| { - stack.append(State { .BinaryXorExpressionEnd = opt_ctx }) catch unreachable; - try stack.append(State { .BinaryAndExpressionBegin = opt_ctx }); + stack.append(State{ .BinaryXorExpressionEnd = opt_ctx }) catch unreachable; + try stack.append(State{ .BinaryAndExpressionBegin = opt_ctx }); continue; }, @@ -2037,23 +1888,23 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { const lhs = opt_ctx.get() ?? continue; if (eatToken(&tok_it, &tree, Token.Id.Caret)) |caret| { - const node = try arena.construct(ast.Node.InfixOp { - .base = ast.Node {.id = ast.Node.Id.InfixOp }, + const node = try arena.construct(ast.Node.InfixOp{ + .base = ast.Node{ .id = ast.Node.Id.InfixOp }, .lhs = lhs, .op_token = caret, .op = ast.Node.InfixOp.Op.BitXor, .rhs = undefined, }); opt_ctx.store(&node.base); - stack.append(State { .BinaryXorExpressionEnd = opt_ctx.toRequired() }) catch unreachable; - try stack.append(State { .BinaryAndExpressionBegin = OptionalCtx { .Required = &node.rhs } }); + stack.append(State{ .BinaryXorExpressionEnd = opt_ctx.toRequired() }) catch unreachable; + try stack.append(State{ .BinaryAndExpressionBegin = OptionalCtx{ .Required = &node.rhs } }); continue; } }, State.BinaryAndExpressionBegin => |opt_ctx| { - stack.append(State { .BinaryAndExpressionEnd = opt_ctx }) catch unreachable; - try stack.append(State { .BitShiftExpressionBegin = opt_ctx }); + stack.append(State{ .BinaryAndExpressionEnd = opt_ctx }) catch unreachable; + try stack.append(State{ .BitShiftExpressionBegin = opt_ctx }); continue; }, @@ -2061,23 +1912,23 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { const lhs = opt_ctx.get() ?? continue; if (eatToken(&tok_it, &tree, Token.Id.Ampersand)) |ampersand| { - const node = try arena.construct(ast.Node.InfixOp { - .base = ast.Node {.id = ast.Node.Id.InfixOp }, + const node = try arena.construct(ast.Node.InfixOp{ + .base = ast.Node{ .id = ast.Node.Id.InfixOp }, .lhs = lhs, .op_token = ampersand, .op = ast.Node.InfixOp.Op.BitAnd, .rhs = undefined, }); opt_ctx.store(&node.base); - stack.append(State { .BinaryAndExpressionEnd = opt_ctx.toRequired() }) catch unreachable; - try stack.append(State { .BitShiftExpressionBegin = OptionalCtx { .Required = &node.rhs } }); + stack.append(State{ .BinaryAndExpressionEnd = opt_ctx.toRequired() }) catch unreachable; + try stack.append(State{ .BitShiftExpressionBegin = OptionalCtx{ .Required = &node.rhs } }); continue; } }, State.BitShiftExpressionBegin => |opt_ctx| { - stack.append(State { .BitShiftExpressionEnd = opt_ctx }) catch unreachable; - try stack.append(State { .AdditionExpressionBegin = opt_ctx }); + stack.append(State{ .BitShiftExpressionEnd = opt_ctx }) catch unreachable; + try stack.append(State{ .AdditionExpressionBegin = opt_ctx }); continue; }, @@ -2088,16 +1939,16 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { const token_index = token.index; const token_ptr = token.ptr; if (tokenIdToBitShift(token_ptr.id)) |bitshift_id| { - const node = try arena.construct(ast.Node.InfixOp { - .base = ast.Node {.id = ast.Node.Id.InfixOp }, + const node = try arena.construct(ast.Node.InfixOp{ + .base = ast.Node{ .id = ast.Node.Id.InfixOp }, .lhs = lhs, .op_token = token_index, .op = bitshift_id, .rhs = undefined, }); opt_ctx.store(&node.base); - stack.append(State { .BitShiftExpressionEnd = opt_ctx.toRequired() }) catch unreachable; - try stack.append(State { .AdditionExpressionBegin = OptionalCtx { .Required = &node.rhs } }); + stack.append(State{ .BitShiftExpressionEnd = opt_ctx.toRequired() }) catch unreachable; + try stack.append(State{ .AdditionExpressionBegin = OptionalCtx{ .Required = &node.rhs } }); continue; } else { putBackToken(&tok_it, &tree); @@ -2106,8 +1957,8 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { }, State.AdditionExpressionBegin => |opt_ctx| { - stack.append(State { .AdditionExpressionEnd = opt_ctx }) catch unreachable; - try stack.append(State { .MultiplyExpressionBegin = opt_ctx }); + stack.append(State{ .AdditionExpressionEnd = opt_ctx }) catch unreachable; + try stack.append(State{ .MultiplyExpressionBegin = opt_ctx }); continue; }, @@ -2118,16 +1969,16 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { const token_index = token.index; const token_ptr = token.ptr; if (tokenIdToAddition(token_ptr.id)) |add_id| { - const node = try arena.construct(ast.Node.InfixOp { - .base = ast.Node {.id = ast.Node.Id.InfixOp }, + const node = try arena.construct(ast.Node.InfixOp{ + .base = ast.Node{ .id = ast.Node.Id.InfixOp }, .lhs = lhs, .op_token = token_index, .op = add_id, .rhs = undefined, }); opt_ctx.store(&node.base); - stack.append(State { .AdditionExpressionEnd = opt_ctx.toRequired() }) catch unreachable; - try stack.append(State { .MultiplyExpressionBegin = OptionalCtx { .Required = &node.rhs } }); + stack.append(State{ .AdditionExpressionEnd = opt_ctx.toRequired() }) catch unreachable; + try stack.append(State{ .MultiplyExpressionBegin = OptionalCtx{ .Required = &node.rhs } }); continue; } else { putBackToken(&tok_it, &tree); @@ -2136,8 +1987,8 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { }, State.MultiplyExpressionBegin => |opt_ctx| { - stack.append(State { .MultiplyExpressionEnd = opt_ctx }) catch unreachable; - try stack.append(State { .CurlySuffixExpressionBegin = opt_ctx }); + stack.append(State{ .MultiplyExpressionEnd = opt_ctx }) catch unreachable; + try stack.append(State{ .CurlySuffixExpressionBegin = opt_ctx }); continue; }, @@ -2148,16 +1999,16 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { const token_index = token.index; const token_ptr = token.ptr; if (tokenIdToMultiply(token_ptr.id)) |mult_id| { - const node = try arena.construct(ast.Node.InfixOp { - .base = ast.Node {.id = ast.Node.Id.InfixOp }, + const node = try arena.construct(ast.Node.InfixOp{ + .base = ast.Node{ .id = ast.Node.Id.InfixOp }, .lhs = lhs, .op_token = token_index, .op = mult_id, .rhs = undefined, }); opt_ctx.store(&node.base); - stack.append(State { .MultiplyExpressionEnd = opt_ctx.toRequired() }) catch unreachable; - try stack.append(State { .CurlySuffixExpressionBegin = OptionalCtx { .Required = &node.rhs } }); + stack.append(State{ .MultiplyExpressionEnd = opt_ctx.toRequired() }) catch unreachable; + try stack.append(State{ .CurlySuffixExpressionBegin = OptionalCtx{ .Required = &node.rhs } }); continue; } else { putBackToken(&tok_it, &tree); @@ -2166,9 +2017,9 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { }, State.CurlySuffixExpressionBegin => |opt_ctx| { - stack.append(State { .CurlySuffixExpressionEnd = opt_ctx }) catch unreachable; - try stack.append(State { .IfToken = Token.Id.LBrace }); - try stack.append(State { .TypeExprBegin = opt_ctx }); + stack.append(State{ .CurlySuffixExpressionEnd = opt_ctx }) catch unreachable; + try stack.append(State{ .IfToken = Token.Id.LBrace }); + try stack.append(State{ .TypeExprBegin = opt_ctx }); continue; }, @@ -2176,51 +2027,43 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { const lhs = opt_ctx.get() ?? continue; if ((??tok_it.peek()).id == Token.Id.Period) { - const node = try arena.construct(ast.Node.SuffixOp { - .base = ast.Node { .id = ast.Node.Id.SuffixOp }, + const node = try arena.construct(ast.Node.SuffixOp{ + .base = ast.Node{ .id = ast.Node.Id.SuffixOp }, .lhs = lhs, - .op = ast.Node.SuffixOp.Op { - .StructInitializer = ast.Node.SuffixOp.Op.InitList.init(arena), - }, + .op = ast.Node.SuffixOp.Op{ .StructInitializer = ast.Node.SuffixOp.Op.InitList.init(arena) }, .rtoken = undefined, }); opt_ctx.store(&node.base); - stack.append(State { .CurlySuffixExpressionEnd = opt_ctx.toRequired() }) catch unreachable; - try stack.append(State { .IfToken = Token.Id.LBrace }); - try stack.append(State { - .FieldInitListItemOrEnd = ListSave(@typeOf(node.op.StructInitializer)) { - .list = &node.op.StructInitializer, - .ptr = &node.rtoken, - } - }); + stack.append(State{ .CurlySuffixExpressionEnd = opt_ctx.toRequired() }) catch unreachable; + try stack.append(State{ .IfToken = Token.Id.LBrace }); + try stack.append(State{ .FieldInitListItemOrEnd = ListSave(@typeOf(node.op.StructInitializer)){ + .list = &node.op.StructInitializer, + .ptr = &node.rtoken, + } }); continue; } - const node = try arena.construct(ast.Node.SuffixOp { - .base = ast.Node {.id = ast.Node.Id.SuffixOp }, + const node = try arena.construct(ast.Node.SuffixOp{ + .base = ast.Node{ .id = ast.Node.Id.SuffixOp }, .lhs = lhs, - .op = ast.Node.SuffixOp.Op { - .ArrayInitializer = ast.Node.SuffixOp.Op.InitList.init(arena), - }, + .op = ast.Node.SuffixOp.Op{ .ArrayInitializer = ast.Node.SuffixOp.Op.InitList.init(arena) }, .rtoken = undefined, }); opt_ctx.store(&node.base); - stack.append(State { .CurlySuffixExpressionEnd = opt_ctx.toRequired() }) catch unreachable; - try stack.append(State { .IfToken = Token.Id.LBrace }); - try stack.append(State { - .ExprListItemOrEnd = ExprListCtx { - .list = &node.op.ArrayInitializer, - .end = Token.Id.RBrace, - .ptr = &node.rtoken, - } - }); + stack.append(State{ .CurlySuffixExpressionEnd = opt_ctx.toRequired() }) catch unreachable; + try stack.append(State{ .IfToken = Token.Id.LBrace }); + try stack.append(State{ .ExprListItemOrEnd = ExprListCtx{ + .list = &node.op.ArrayInitializer, + .end = Token.Id.RBrace, + .ptr = &node.rtoken, + } }); continue; }, State.TypeExprBegin => |opt_ctx| { - stack.append(State { .TypeExprEnd = opt_ctx }) catch unreachable; - try stack.append(State { .PrefixOpExpression = opt_ctx }); + stack.append(State{ .TypeExprEnd = opt_ctx }) catch unreachable; + try stack.append(State{ .PrefixOpExpression = opt_ctx }); continue; }, @@ -2228,16 +2071,16 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { const lhs = opt_ctx.get() ?? continue; if (eatToken(&tok_it, &tree, Token.Id.Bang)) |bang| { - const node = try arena.construct(ast.Node.InfixOp { - .base = ast.Node {.id = ast.Node.Id.InfixOp }, + const node = try arena.construct(ast.Node.InfixOp{ + .base = ast.Node{ .id = ast.Node.Id.InfixOp }, .lhs = lhs, .op_token = bang, .op = ast.Node.InfixOp.Op.ErrorUnion, .rhs = undefined, }); opt_ctx.store(&node.base); - stack.append(State { .TypeExprEnd = opt_ctx.toRequired() }) catch unreachable; - try stack.append(State { .PrefixOpExpression = OptionalCtx { .Required = &node.rhs } }); + stack.append(State{ .TypeExprEnd = opt_ctx.toRequired() }) catch unreachable; + try stack.append(State{ .PrefixOpExpression = OptionalCtx{ .Required = &node.rhs } }); continue; } }, @@ -2247,8 +2090,8 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { const token_index = token.index; const token_ptr = token.ptr; if (tokenIdToPrefixOp(token_ptr.id)) |prefix_id| { - var node = try arena.construct(ast.Node.PrefixOp { - .base = ast.Node {.id = ast.Node.Id.PrefixOp }, + var node = try arena.construct(ast.Node.PrefixOp{ + .base = ast.Node{ .id = ast.Node.Id.PrefixOp }, .op_token = token_index, .op = prefix_id, .rhs = undefined, @@ -2257,8 +2100,8 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { // Treat '**' token as two derefs if (token_ptr.id == Token.Id.AsteriskAsterisk) { - const child = try arena.construct(ast.Node.PrefixOp { - .base = ast.Node {.id = ast.Node.Id.PrefixOp}, + const child = try arena.construct(ast.Node.PrefixOp{ + .base = ast.Node{ .id = ast.Node.Id.PrefixOp }, .op_token = token_index, .op = prefix_id, .rhs = undefined, @@ -2267,40 +2110,38 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { node = child; } - stack.append(State { .TypeExprBegin = OptionalCtx { .Required = &node.rhs } }) catch unreachable; + stack.append(State{ .TypeExprBegin = OptionalCtx{ .Required = &node.rhs } }) catch unreachable; if (node.op == ast.Node.PrefixOp.Op.AddrOf) { - try stack.append(State { .AddrOfModifiers = &node.op.AddrOf }); + try stack.append(State{ .AddrOfModifiers = &node.op.AddrOf }); } continue; } else { putBackToken(&tok_it, &tree); - stack.append(State { .SuffixOpExpressionBegin = opt_ctx }) catch unreachable; + stack.append(State{ .SuffixOpExpressionBegin = opt_ctx }) catch unreachable; continue; } }, State.SuffixOpExpressionBegin => |opt_ctx| { if (eatToken(&tok_it, &tree, Token.Id.Keyword_async)) |async_token| { - const async_node = try arena.construct(ast.Node.AsyncAttribute { - .base = ast.Node {.id = ast.Node.Id.AsyncAttribute}, + const async_node = try arena.construct(ast.Node.AsyncAttribute{ + .base = ast.Node{ .id = ast.Node.Id.AsyncAttribute }, .async_token = async_token, .allocator_type = null, .rangle_bracket = null, }); - stack.append(State { - .AsyncEnd = AsyncEndCtx { - .ctx = opt_ctx, - .attribute = async_node, - } - }) catch unreachable; - try stack.append(State { .SuffixOpExpressionEnd = opt_ctx.toRequired() }); - try stack.append(State { .PrimaryExpression = opt_ctx.toRequired() }); - try stack.append(State { .AsyncAllocator = async_node }); + stack.append(State{ .AsyncEnd = AsyncEndCtx{ + .ctx = opt_ctx, + .attribute = async_node, + } }) catch unreachable; + try stack.append(State{ .SuffixOpExpressionEnd = opt_ctx.toRequired() }); + try stack.append(State{ .PrimaryExpression = opt_ctx.toRequired() }); + try stack.append(State{ .AsyncAllocator = async_node }); continue; } - stack.append(State { .SuffixOpExpressionEnd = opt_ctx }) catch unreachable; - try stack.append(State { .PrimaryExpression = opt_ctx }); + stack.append(State{ .SuffixOpExpressionEnd = opt_ctx }) catch unreachable; + try stack.append(State{ .PrimaryExpression = opt_ctx }); continue; }, @@ -2312,48 +2153,42 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { const token_ptr = token.ptr; switch (token_ptr.id) { Token.Id.LParen => { - const node = try arena.construct(ast.Node.SuffixOp { - .base = ast.Node {.id = ast.Node.Id.SuffixOp }, + const node = try arena.construct(ast.Node.SuffixOp{ + .base = ast.Node{ .id = ast.Node.Id.SuffixOp }, .lhs = lhs, - .op = ast.Node.SuffixOp.Op { - .Call = ast.Node.SuffixOp.Op.Call { - .params = ast.Node.SuffixOp.Op.Call.ParamList.init(arena), - .async_attr = null, - } - }, + .op = ast.Node.SuffixOp.Op{ .Call = ast.Node.SuffixOp.Op.Call{ + .params = ast.Node.SuffixOp.Op.Call.ParamList.init(arena), + .async_attr = null, + } }, .rtoken = undefined, }); opt_ctx.store(&node.base); - stack.append(State { .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable; - try stack.append(State { - .ExprListItemOrEnd = ExprListCtx { - .list = &node.op.Call.params, - .end = Token.Id.RParen, - .ptr = &node.rtoken, - } - }); + stack.append(State{ .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable; + try stack.append(State{ .ExprListItemOrEnd = ExprListCtx{ + .list = &node.op.Call.params, + .end = Token.Id.RParen, + .ptr = &node.rtoken, + } }); continue; }, Token.Id.LBracket => { - const node = try arena.construct(ast.Node.SuffixOp { - .base = ast.Node {.id = ast.Node.Id.SuffixOp }, + const node = try arena.construct(ast.Node.SuffixOp{ + .base = ast.Node{ .id = ast.Node.Id.SuffixOp }, .lhs = lhs, - .op = ast.Node.SuffixOp.Op { - .ArrayAccess = undefined, - }, - .rtoken = undefined + .op = ast.Node.SuffixOp.Op{ .ArrayAccess = undefined }, + .rtoken = undefined, }); opt_ctx.store(&node.base); - stack.append(State { .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable; - try stack.append(State { .SliceOrArrayAccess = node }); - try stack.append(State { .Expression = OptionalCtx { .Required = &node.op.ArrayAccess }}); + stack.append(State{ .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable; + try stack.append(State{ .SliceOrArrayAccess = node }); + try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.op.ArrayAccess } }); continue; }, Token.Id.Period => { - const node = try arena.construct(ast.Node.InfixOp { - .base = ast.Node {.id = ast.Node.Id.InfixOp }, + const node = try arena.construct(ast.Node.InfixOp{ + .base = ast.Node{ .id = ast.Node.Id.InfixOp }, .lhs = lhs, .op_token = token_index, .op = ast.Node.InfixOp.Op.Period, @@ -2361,8 +2196,8 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { }); opt_ctx.store(&node.base); - stack.append(State { .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable; - try stack.append(State { .Identifier = OptionalCtx { .Required = &node.rhs } }); + stack.append(State{ .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable; + try stack.append(State{ .Identifier = OptionalCtx{ .Required = &node.rhs } }); continue; }, else => { @@ -2391,7 +2226,8 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { _ = try createToCtxLiteral(arena, opt_ctx, ast.Node.UndefinedLiteral, token.index); continue; }, - Token.Id.Keyword_true, Token.Id.Keyword_false => { + Token.Id.Keyword_true, + Token.Id.Keyword_false => { _ = try createToCtxLiteral(arena, opt_ctx, ast.Node.BoolLiteral, token.index); continue; }, @@ -2412,10 +2248,8 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { continue; }, Token.Id.Keyword_promise => { - const node = try arena.construct(ast.Node.PromiseType { - .base = ast.Node { - .id = ast.Node.Id.PromiseType, - }, + const node = try arena.construct(ast.Node.PromiseType{ + .base = ast.Node{ .id = ast.Node.Id.PromiseType }, .promise_token = token.index, .result = null, }); @@ -2427,121 +2261,108 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { putBackToken(&tok_it, &tree); continue; } - node.result = ast.Node.PromiseType.Result { + node.result = ast.Node.PromiseType.Result{ .arrow_token = next_token_index, .return_type = undefined, }; const return_type_ptr = &((??node.result).return_type); - try stack.append(State { .Expression = OptionalCtx { .Required = return_type_ptr, } }); + try stack.append(State{ .Expression = OptionalCtx{ .Required = return_type_ptr } }); continue; }, - Token.Id.StringLiteral, Token.Id.MultilineStringLiteralLine => { + Token.Id.StringLiteral, + Token.Id.MultilineStringLiteralLine => { opt_ctx.store((try parseStringLiteral(arena, &tok_it, token.ptr, token.index, &tree)) ?? unreachable); continue; }, Token.Id.LParen => { - const node = try arena.construct(ast.Node.GroupedExpression { - .base = ast.Node {.id = ast.Node.Id.GroupedExpression }, + const node = try arena.construct(ast.Node.GroupedExpression{ + .base = ast.Node{ .id = ast.Node.Id.GroupedExpression }, .lparen = token.index, .expr = undefined, .rparen = undefined, }); opt_ctx.store(&node.base); - stack.append(State { - .ExpectTokenSave = ExpectTokenSave { - .id = Token.Id.RParen, - .ptr = &node.rparen, - } - }) catch unreachable; - try stack.append(State { .Expression = OptionalCtx { .Required = &node.expr } }); + stack.append(State{ .ExpectTokenSave = ExpectTokenSave{ + .id = Token.Id.RParen, + .ptr = &node.rparen, + } }) catch unreachable; + try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.expr } }); continue; }, Token.Id.Builtin => { - const node = try arena.construct(ast.Node.BuiltinCall { - .base = ast.Node {.id = ast.Node.Id.BuiltinCall }, + const node = try arena.construct(ast.Node.BuiltinCall{ + .base = ast.Node{ .id = ast.Node.Id.BuiltinCall }, .builtin_token = token.index, .params = ast.Node.BuiltinCall.ParamList.init(arena), .rparen_token = undefined, }); opt_ctx.store(&node.base); - stack.append(State { - .ExprListItemOrEnd = ExprListCtx { - .list = &node.params, - .end = Token.Id.RParen, - .ptr = &node.rparen_token, - } - }) catch unreachable; - try stack.append(State { .ExpectToken = Token.Id.LParen, }); + stack.append(State{ .ExprListItemOrEnd = ExprListCtx{ + .list = &node.params, + .end = Token.Id.RParen, + .ptr = &node.rparen_token, + } }) catch unreachable; + try stack.append(State{ .ExpectToken = Token.Id.LParen }); continue; }, Token.Id.LBracket => { - const node = try arena.construct(ast.Node.PrefixOp { - .base = ast.Node {.id = ast.Node.Id.PrefixOp }, + const node = try arena.construct(ast.Node.PrefixOp{ + .base = ast.Node{ .id = ast.Node.Id.PrefixOp }, .op_token = token.index, .op = undefined, .rhs = undefined, }); opt_ctx.store(&node.base); - stack.append(State { .SliceOrArrayType = node }) catch unreachable; + stack.append(State{ .SliceOrArrayType = node }) catch unreachable; continue; }, Token.Id.Keyword_error => { - stack.append(State { - .ErrorTypeOrSetDecl = ErrorTypeOrSetDeclCtx { - .error_token = token.index, - .opt_ctx = opt_ctx - } - }) catch unreachable; + stack.append(State{ .ErrorTypeOrSetDecl = ErrorTypeOrSetDeclCtx{ + .error_token = token.index, + .opt_ctx = opt_ctx, + } }) catch unreachable; continue; }, Token.Id.Keyword_packed => { - stack.append(State { - .ContainerKind = ContainerKindCtx { - .opt_ctx = opt_ctx, - .ltoken = token.index, - .layout = ast.Node.ContainerDecl.Layout.Packed, - }, - }) catch unreachable; + stack.append(State{ .ContainerKind = ContainerKindCtx{ + .opt_ctx = opt_ctx, + .ltoken = token.index, + .layout = ast.Node.ContainerDecl.Layout.Packed, + } }) catch unreachable; continue; }, Token.Id.Keyword_extern => { - stack.append(State { - .ExternType = ExternTypeCtx { - .opt_ctx = opt_ctx, - .extern_token = token.index, - .comments = null, - }, - }) catch unreachable; + stack.append(State{ .ExternType = ExternTypeCtx{ + .opt_ctx = opt_ctx, + .extern_token = token.index, + .comments = null, + } }) catch unreachable; continue; }, - Token.Id.Keyword_struct, Token.Id.Keyword_union, Token.Id.Keyword_enum => { + Token.Id.Keyword_struct, + Token.Id.Keyword_union, + Token.Id.Keyword_enum => { putBackToken(&tok_it, &tree); - stack.append(State { - .ContainerKind = ContainerKindCtx { - .opt_ctx = opt_ctx, - .ltoken = token.index, - .layout = ast.Node.ContainerDecl.Layout.Auto, - }, - }) catch unreachable; + stack.append(State{ .ContainerKind = ContainerKindCtx{ + .opt_ctx = opt_ctx, + .ltoken = token.index, + .layout = ast.Node.ContainerDecl.Layout.Auto, + } }) catch unreachable; continue; }, Token.Id.Identifier => { - stack.append(State { - .MaybeLabeledExpression = MaybeLabeledExpressionCtx { - .label = token.index, - .opt_ctx = opt_ctx - } - }) catch unreachable; + stack.append(State{ .MaybeLabeledExpression = MaybeLabeledExpressionCtx{ + .label = token.index, + .opt_ctx = opt_ctx, + } }) catch unreachable; continue; }, Token.Id.Keyword_fn => { - const fn_proto = try arena.construct(ast.Node.FnProto { - .base = ast.Node { - .id = ast.Node.Id.FnProto, - }, + const fn_proto = try arena.construct(ast.Node.FnProto{ + .base = ast.Node{ .id = ast.Node.Id.FnProto }, .doc_comments = null, .visib_token = null, .name_token = null, @@ -2557,14 +2378,13 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { .align_expr = null, }); opt_ctx.store(&fn_proto.base); - stack.append(State { .FnProto = fn_proto }) catch unreachable; + stack.append(State{ .FnProto = fn_proto }) catch unreachable; continue; }, - Token.Id.Keyword_nakedcc, Token.Id.Keyword_stdcallcc => { - const fn_proto = try arena.construct(ast.Node.FnProto { - .base = ast.Node { - .id = ast.Node.Id.FnProto, - }, + Token.Id.Keyword_nakedcc, + Token.Id.Keyword_stdcallcc => { + const fn_proto = try arena.construct(ast.Node.FnProto{ + .base = ast.Node{ .id = ast.Node.Id.FnProto }, .doc_comments = null, .visib_token = null, .name_token = null, @@ -2580,18 +2400,16 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { .align_expr = null, }); opt_ctx.store(&fn_proto.base); - stack.append(State { .FnProto = fn_proto }) catch unreachable; - try stack.append(State { - .ExpectTokenSave = ExpectTokenSave { - .id = Token.Id.Keyword_fn, - .ptr = &fn_proto.fn_token - } - }); + stack.append(State{ .FnProto = fn_proto }) catch unreachable; + try stack.append(State{ .ExpectTokenSave = ExpectTokenSave{ + .id = Token.Id.Keyword_fn, + .ptr = &fn_proto.fn_token, + } }); continue; }, Token.Id.Keyword_asm => { - const node = try arena.construct(ast.Node.Asm { - .base = ast.Node {.id = ast.Node.Id.Asm }, + const node = try arena.construct(ast.Node.Asm{ + .base = ast.Node{ .id = ast.Node.Id.Asm }, .asm_token = token.index, .volatile_token = null, .template = undefined, @@ -2602,94 +2420,77 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { }); opt_ctx.store(&node.base); - stack.append(State { - .ExpectTokenSave = ExpectTokenSave { - .id = Token.Id.RParen, - .ptr = &node.rparen, - } - }) catch unreachable; - try stack.append(State { .AsmClobberItems = &node.clobbers }); - try stack.append(State { .IfToken = Token.Id.Colon }); - try stack.append(State { .AsmInputItems = &node.inputs }); - try stack.append(State { .IfToken = Token.Id.Colon }); - try stack.append(State { .AsmOutputItems = &node.outputs }); - try stack.append(State { .IfToken = Token.Id.Colon }); - try stack.append(State { .StringLiteral = OptionalCtx { .Required = &node.template } }); - try stack.append(State { .ExpectToken = Token.Id.LParen }); - try stack.append(State { - .OptionalTokenSave = OptionalTokenSave { - .id = Token.Id.Keyword_volatile, - .ptr = &node.volatile_token, - } - }); + stack.append(State{ .ExpectTokenSave = ExpectTokenSave{ + .id = Token.Id.RParen, + .ptr = &node.rparen, + } }) catch unreachable; + try stack.append(State{ .AsmClobberItems = &node.clobbers }); + try stack.append(State{ .IfToken = Token.Id.Colon }); + try stack.append(State{ .AsmInputItems = &node.inputs }); + try stack.append(State{ .IfToken = Token.Id.Colon }); + try stack.append(State{ .AsmOutputItems = &node.outputs }); + try stack.append(State{ .IfToken = Token.Id.Colon }); + try stack.append(State{ .StringLiteral = OptionalCtx{ .Required = &node.template } }); + try stack.append(State{ .ExpectToken = Token.Id.LParen }); + try stack.append(State{ .OptionalTokenSave = OptionalTokenSave{ + .id = Token.Id.Keyword_volatile, + .ptr = &node.volatile_token, + } }); }, Token.Id.Keyword_inline => { - stack.append(State { - .Inline = InlineCtx { - .label = null, - .inline_token = token.index, - .opt_ctx = opt_ctx, - } - }) catch unreachable; + stack.append(State{ .Inline = InlineCtx{ + .label = null, + .inline_token = token.index, + .opt_ctx = opt_ctx, + } }) catch unreachable; continue; }, else => { if (!try parseBlockExpr(&stack, arena, opt_ctx, token.ptr, token.index)) { putBackToken(&tok_it, &tree); if (opt_ctx != OptionalCtx.Optional) { - *(try tree.errors.addOne()) = Error { - .ExpectedPrimaryExpr = Error.ExpectedPrimaryExpr { .token = token.index }, - }; + ((try tree.errors.addOne())).* = Error{ .ExpectedPrimaryExpr = Error.ExpectedPrimaryExpr{ .token = token.index } }; return tree; } } continue; - } + }, } }, - State.ErrorTypeOrSetDecl => |ctx| { if (eatToken(&tok_it, &tree, Token.Id.LBrace) == null) { _ = try createToCtxLiteral(arena, ctx.opt_ctx, ast.Node.ErrorType, ctx.error_token); continue; } - const node = try arena.construct(ast.Node.ErrorSetDecl { - .base = ast.Node { - .id = ast.Node.Id.ErrorSetDecl, - }, + const node = try arena.construct(ast.Node.ErrorSetDecl{ + .base = ast.Node{ .id = ast.Node.Id.ErrorSetDecl }, .error_token = ctx.error_token, .decls = ast.Node.ErrorSetDecl.DeclList.init(arena), .rbrace_token = undefined, }); ctx.opt_ctx.store(&node.base); - stack.append(State { - .ErrorTagListItemOrEnd = ListSave(@typeOf(node.decls)) { - .list = &node.decls, - .ptr = &node.rbrace_token, - } - }) catch unreachable; + stack.append(State{ .ErrorTagListItemOrEnd = ListSave(@typeOf(node.decls)){ + .list = &node.decls, + .ptr = &node.rbrace_token, + } }) catch unreachable; continue; }, State.StringLiteral => |opt_ctx| { const token = nextToken(&tok_it, &tree); const token_index = token.index; const token_ptr = token.ptr; - opt_ctx.store( - (try parseStringLiteral(arena, &tok_it, token_ptr, token_index, &tree)) ?? { - putBackToken(&tok_it, &tree); - if (opt_ctx != OptionalCtx.Optional) { - *(try tree.errors.addOne()) = Error { - .ExpectedPrimaryExpr = Error.ExpectedPrimaryExpr { .token = token_index }, - }; - return tree; - } - - continue; + opt_ctx.store((try parseStringLiteral(arena, &tok_it, token_ptr, token_index, &tree)) ?? { + putBackToken(&tok_it, &tree); + if (opt_ctx != OptionalCtx.Optional) { + ((try tree.errors.addOne())).* = Error{ .ExpectedPrimaryExpr = Error.ExpectedPrimaryExpr{ .token = token_index } }; + return tree; } - ); + + continue; + }); }, State.Identifier => |opt_ctx| { @@ -2702,12 +2503,10 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { const token = nextToken(&tok_it, &tree); const token_index = token.index; const token_ptr = token.ptr; - *(try tree.errors.addOne()) = Error { - .ExpectedToken = Error.ExpectedToken { - .token = token_index, - .expected_id = Token.Id.Identifier, - }, - }; + ((try tree.errors.addOne())).* = Error{ .ExpectedToken = Error.ExpectedToken{ + .token = token_index, + .expected_id = Token.Id.Identifier, + } }; return tree; } }, @@ -2718,23 +2517,19 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { const ident_token_index = ident_token.index; const ident_token_ptr = ident_token.ptr; if (ident_token_ptr.id != Token.Id.Identifier) { - *(try tree.errors.addOne()) = Error { - .ExpectedToken = Error.ExpectedToken { - .token = ident_token_index, - .expected_id = Token.Id.Identifier, - }, - }; + ((try tree.errors.addOne())).* = Error{ .ExpectedToken = Error.ExpectedToken{ + .token = ident_token_index, + .expected_id = Token.Id.Identifier, + } }; return tree; } - const node = try arena.construct(ast.Node.ErrorTag { - .base = ast.Node { - .id = ast.Node.Id.ErrorTag, - }, + const node = try arena.construct(ast.Node.ErrorTag{ + .base = ast.Node{ .id = ast.Node.Id.ErrorTag }, .doc_comments = comments, .name_token = ident_token_index, }); - *node_ptr = &node.base; + node_ptr.* = &node.base; continue; }, @@ -2743,12 +2538,10 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { const token_index = token.index; const token_ptr = token.ptr; if (token_ptr.id != token_id) { - *(try tree.errors.addOne()) = Error { - .ExpectedToken = Error.ExpectedToken { - .token = token_index, - .expected_id = token_id, - }, - }; + ((try tree.errors.addOne())).* = Error{ .ExpectedToken = Error.ExpectedToken{ + .token = token_index, + .expected_id = token_id, + } }; return tree; } continue; @@ -2758,15 +2551,13 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { const token_index = token.index; const token_ptr = token.ptr; if (token_ptr.id != expect_token_save.id) { - *(try tree.errors.addOne()) = Error { - .ExpectedToken = Error.ExpectedToken { - .token = token_index, - .expected_id = expect_token_save.id, - }, - }; + ((try tree.errors.addOne())).* = Error{ .ExpectedToken = Error.ExpectedToken{ + .token = token_index, + .expected_id = expect_token_save.id, + } }; return tree; } - *expect_token_save.ptr = token_index; + (expect_token_save.ptr).* = token_index; continue; }, State.IfToken => |token_id| { @@ -2779,7 +2570,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { }, State.IfTokenSave => |if_token_save| { if (eatToken(&tok_it, &tree, if_token_save.id)) |token_index| { - *if_token_save.ptr = token_index; + (if_token_save.ptr).* = token_index; continue; } @@ -2788,7 +2579,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { }, State.OptionalTokenSave => |optional_token_save| { if (eatToken(&tok_it, &tree, optional_token_save.id)) |token_index| { - *optional_token_save.ptr = token_index; + (optional_token_save.ptr).* = token_index; continue; } @@ -2911,28 +2702,28 @@ const OptionalCtx = union(enum) { Required: &&ast.Node, pub fn store(self: &const OptionalCtx, value: &ast.Node) void { - switch (*self) { - OptionalCtx.Optional => |ptr| *ptr = value, - OptionalCtx.RequiredNull => |ptr| *ptr = value, - OptionalCtx.Required => |ptr| *ptr = value, + switch (self.*) { + OptionalCtx.Optional => |ptr| ptr.* = value, + OptionalCtx.RequiredNull => |ptr| ptr.* = value, + OptionalCtx.Required => |ptr| ptr.* = value, } } pub fn get(self: &const OptionalCtx) ?&ast.Node { - switch (*self) { - OptionalCtx.Optional => |ptr| return *ptr, - OptionalCtx.RequiredNull => |ptr| return ??*ptr, - OptionalCtx.Required => |ptr| return *ptr, + switch (self.*) { + OptionalCtx.Optional => |ptr| return ptr.*, + OptionalCtx.RequiredNull => |ptr| return ??ptr.*, + OptionalCtx.Required => |ptr| return ptr.*, } } pub fn toRequired(self: &const OptionalCtx) OptionalCtx { - switch (*self) { + switch (self.*) { OptionalCtx.Optional => |ptr| { - return OptionalCtx { .RequiredNull = ptr }; + return OptionalCtx{ .RequiredNull = ptr }; }, - OptionalCtx.RequiredNull => |ptr| return *self, - OptionalCtx.Required => |ptr| return *self, + OptionalCtx.RequiredNull => |ptr| return self.*, + OptionalCtx.Required => |ptr| return self.*, } } }; @@ -3054,7 +2845,6 @@ const State = union(enum) { Identifier: OptionalCtx, ErrorTag: &&ast.Node, - IfToken: @TagType(Token.Id), IfTokenSave: ExpectTokenSave, ExpectToken: @TagType(Token.Id), @@ -3064,16 +2854,14 @@ const State = union(enum) { fn pushDocComment(arena: &mem.Allocator, line_comment: TokenIndex, result: &?&ast.Node.DocComment) !void { const node = blk: { - if (*result) |comment_node| { + if (result.*) |comment_node| { break :blk comment_node; } else { - const comment_node = try arena.construct(ast.Node.DocComment { - .base = ast.Node { - .id = ast.Node.Id.DocComment, - }, + const comment_node = try arena.construct(ast.Node.DocComment{ + .base = ast.Node{ .id = ast.Node.Id.DocComment }, .lines = ast.Node.DocComment.LineList.init(arena), }); - *result = comment_node; + result.* = comment_node; break :blk comment_node; } }; @@ -3094,24 +2882,20 @@ fn eatDocComments(arena: &mem.Allocator, tok_it: &ast.Tree.TokenList.Iterator, t fn eatLineComment(arena: &mem.Allocator, tok_it: &ast.Tree.TokenList.Iterator, tree: &ast.Tree) !?&ast.Node.LineComment { const token = eatToken(tok_it, tree, Token.Id.LineComment) ?? return null; - return try arena.construct(ast.Node.LineComment { - .base = ast.Node { - .id = ast.Node.Id.LineComment, - }, + return try arena.construct(ast.Node.LineComment{ + .base = ast.Node{ .id = ast.Node.Id.LineComment }, .token = token, }); } -fn parseStringLiteral(arena: &mem.Allocator, tok_it: &ast.Tree.TokenList.Iterator, - token_ptr: &const Token, token_index: TokenIndex, tree: &ast.Tree) !?&ast.Node -{ +fn parseStringLiteral(arena: &mem.Allocator, tok_it: &ast.Tree.TokenList.Iterator, token_ptr: &const Token, token_index: TokenIndex, tree: &ast.Tree) !?&ast.Node { switch (token_ptr.id) { Token.Id.StringLiteral => { return &(try createLiteral(arena, ast.Node.StringLiteral, token_index)).base; }, Token.Id.MultilineStringLiteralLine => { - const node = try arena.construct(ast.Node.MultilineStringLiteral { - .base = ast.Node { .id = ast.Node.Id.MultilineStringLiteral }, + const node = try arena.construct(ast.Node.MultilineStringLiteral{ + .base = ast.Node{ .id = ast.Node.Id.MultilineStringLiteral }, .lines = ast.Node.MultilineStringLiteral.LineList.init(arena), }); try node.lines.push(token_index); @@ -3135,12 +2919,11 @@ fn parseStringLiteral(arena: &mem.Allocator, tok_it: &ast.Tree.TokenList.Iterato } } -fn parseBlockExpr(stack: &std.ArrayList(State), arena: &mem.Allocator, ctx: &const OptionalCtx, - token_ptr: &const Token, token_index: TokenIndex) !bool { +fn parseBlockExpr(stack: &std.ArrayList(State), arena: &mem.Allocator, ctx: &const OptionalCtx, token_ptr: &const Token, token_index: TokenIndex) !bool { switch (token_ptr.id) { Token.Id.Keyword_suspend => { - const node = try arena.construct(ast.Node.Suspend { - .base = ast.Node {.id = ast.Node.Id.Suspend }, + const node = try arena.construct(ast.Node.Suspend{ + .base = ast.Node{ .id = ast.Node.Id.Suspend }, .label = null, .suspend_token = token_index, .payload = null, @@ -3148,13 +2931,13 @@ fn parseBlockExpr(stack: &std.ArrayList(State), arena: &mem.Allocator, ctx: &con }); ctx.store(&node.base); - stack.append(State { .SuspendBody = node }) catch unreachable; - try stack.append(State { .Payload = OptionalCtx { .Optional = &node.payload } }); + stack.append(State{ .SuspendBody = node }) catch unreachable; + try stack.append(State{ .Payload = OptionalCtx{ .Optional = &node.payload } }); return true; }, Token.Id.Keyword_if => { - const node = try arena.construct(ast.Node.If { - .base = ast.Node {.id = ast.Node.Id.If }, + const node = try arena.construct(ast.Node.If{ + .base = ast.Node{ .id = ast.Node.Id.If }, .if_token = token_index, .condition = undefined, .payload = null, @@ -3163,41 +2946,35 @@ fn parseBlockExpr(stack: &std.ArrayList(State), arena: &mem.Allocator, ctx: &con }); ctx.store(&node.base); - stack.append(State { .Else = &node.@"else" }) catch unreachable; - try stack.append(State { .Expression = OptionalCtx { .Required = &node.body } }); - try stack.append(State { .PointerPayload = OptionalCtx { .Optional = &node.payload } }); - try stack.append(State { .ExpectToken = Token.Id.RParen }); - try stack.append(State { .Expression = OptionalCtx { .Required = &node.condition } }); - try stack.append(State { .ExpectToken = Token.Id.LParen }); + stack.append(State{ .Else = &node.@"else" }) catch unreachable; + try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.body } }); + try stack.append(State{ .PointerPayload = OptionalCtx{ .Optional = &node.payload } }); + try stack.append(State{ .ExpectToken = Token.Id.RParen }); + try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.condition } }); + try stack.append(State{ .ExpectToken = Token.Id.LParen }); return true; }, Token.Id.Keyword_while => { - stack.append(State { - .While = LoopCtx { - .label = null, - .inline_token = null, - .loop_token = token_index, - .opt_ctx = *ctx, - } - }) catch unreachable; + stack.append(State{ .While = LoopCtx{ + .label = null, + .inline_token = null, + .loop_token = token_index, + .opt_ctx = ctx.*, + } }) catch unreachable; return true; }, Token.Id.Keyword_for => { - stack.append(State { - .For = LoopCtx { - .label = null, - .inline_token = null, - .loop_token = token_index, - .opt_ctx = *ctx, - } - }) catch unreachable; + stack.append(State{ .For = LoopCtx{ + .label = null, + .inline_token = null, + .loop_token = token_index, + .opt_ctx = ctx.*, + } }) catch unreachable; return true; }, Token.Id.Keyword_switch => { - const node = try arena.construct(ast.Node.Switch { - .base = ast.Node { - .id = ast.Node.Id.Switch, - }, + const node = try arena.construct(ast.Node.Switch{ + .base = ast.Node{ .id = ast.Node.Id.Switch }, .switch_token = token_index, .expr = undefined, .cases = ast.Node.Switch.CaseList.init(arena), @@ -3205,45 +2982,43 @@ fn parseBlockExpr(stack: &std.ArrayList(State), arena: &mem.Allocator, ctx: &con }); ctx.store(&node.base); - stack.append(State { - .SwitchCaseOrEnd = ListSave(@typeOf(node.cases)) { - .list = &node.cases, - .ptr = &node.rbrace, - }, - }) catch unreachable; - try stack.append(State { .ExpectToken = Token.Id.LBrace }); - try stack.append(State { .ExpectToken = Token.Id.RParen }); - try stack.append(State { .Expression = OptionalCtx { .Required = &node.expr } }); - try stack.append(State { .ExpectToken = Token.Id.LParen }); + stack.append(State{ .SwitchCaseOrEnd = ListSave(@typeOf(node.cases)){ + .list = &node.cases, + .ptr = &node.rbrace, + } }) catch unreachable; + try stack.append(State{ .ExpectToken = Token.Id.LBrace }); + try stack.append(State{ .ExpectToken = Token.Id.RParen }); + try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.expr } }); + try stack.append(State{ .ExpectToken = Token.Id.LParen }); return true; }, Token.Id.Keyword_comptime => { - const node = try arena.construct(ast.Node.Comptime { - .base = ast.Node {.id = ast.Node.Id.Comptime }, + const node = try arena.construct(ast.Node.Comptime{ + .base = ast.Node{ .id = ast.Node.Id.Comptime }, .comptime_token = token_index, .expr = undefined, .doc_comments = null, }); ctx.store(&node.base); - try stack.append(State { .Expression = OptionalCtx { .Required = &node.expr } }); + try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.expr } }); return true; }, Token.Id.LBrace => { - const block = try arena.construct(ast.Node.Block { - .base = ast.Node {.id = ast.Node.Id.Block }, + const block = try arena.construct(ast.Node.Block{ + .base = ast.Node{ .id = ast.Node.Id.Block }, .label = null, .lbrace = token_index, .statements = ast.Node.Block.StatementList.init(arena), .rbrace = undefined, }); ctx.store(&block.base); - stack.append(State { .Block = block }) catch unreachable; + stack.append(State{ .Block = block }) catch unreachable; return true; }, else => { return false; - } + }, } } @@ -3257,20 +3032,16 @@ fn expectCommaOrEnd(tok_it: &ast.Tree.TokenList.Iterator, tree: &ast.Tree, end: const token_index = token.index; const token_ptr = token.ptr; switch (token_ptr.id) { - Token.Id.Comma => return ExpectCommaOrEndResult { .end_token = null}, + Token.Id.Comma => return ExpectCommaOrEndResult{ .end_token = null }, else => { if (end == token_ptr.id) { - return ExpectCommaOrEndResult { .end_token = token_index }; + return ExpectCommaOrEndResult{ .end_token = token_index }; } - return ExpectCommaOrEndResult { - .parse_error = Error { - .ExpectedCommaOrEnd = Error.ExpectedCommaOrEnd { - .token = token_index, - .end_id = end, - }, - }, - }; + return ExpectCommaOrEndResult{ .parse_error = Error{ .ExpectedCommaOrEnd = Error.ExpectedCommaOrEnd{ + .token = token_index, + .end_id = end, + } } }; }, } } @@ -3278,103 +3049,102 @@ fn expectCommaOrEnd(tok_it: &ast.Tree.TokenList.Iterator, tree: &ast.Tree, end: fn tokenIdToAssignment(id: &const Token.Id) ?ast.Node.InfixOp.Op { // TODO: We have to cast all cases because of this: // error: expected type '?InfixOp', found '?@TagType(InfixOp)' - return switch (*id) { - Token.Id.AmpersandEqual => ast.Node.InfixOp.Op { .AssignBitAnd = {} }, - Token.Id.AngleBracketAngleBracketLeftEqual => ast.Node.InfixOp.Op { .AssignBitShiftLeft = {} }, - Token.Id.AngleBracketAngleBracketRightEqual => ast.Node.InfixOp.Op { .AssignBitShiftRight = {} }, - Token.Id.AsteriskEqual => ast.Node.InfixOp.Op { .AssignTimes = {} }, - Token.Id.AsteriskPercentEqual => ast.Node.InfixOp.Op { .AssignTimesWarp = {} }, - Token.Id.CaretEqual => ast.Node.InfixOp.Op { .AssignBitXor = {} }, - Token.Id.Equal => ast.Node.InfixOp.Op { .Assign = {} }, - Token.Id.MinusEqual => ast.Node.InfixOp.Op { .AssignMinus = {} }, - Token.Id.MinusPercentEqual => ast.Node.InfixOp.Op { .AssignMinusWrap = {} }, - Token.Id.PercentEqual => ast.Node.InfixOp.Op { .AssignMod = {} }, - Token.Id.PipeEqual => ast.Node.InfixOp.Op { .AssignBitOr = {} }, - Token.Id.PlusEqual => ast.Node.InfixOp.Op { .AssignPlus = {} }, - Token.Id.PlusPercentEqual => ast.Node.InfixOp.Op { .AssignPlusWrap = {} }, - Token.Id.SlashEqual => ast.Node.InfixOp.Op { .AssignDiv = {} }, + return switch (id.*) { + Token.Id.AmpersandEqual => ast.Node.InfixOp.Op{ .AssignBitAnd = {} }, + Token.Id.AngleBracketAngleBracketLeftEqual => ast.Node.InfixOp.Op{ .AssignBitShiftLeft = {} }, + Token.Id.AngleBracketAngleBracketRightEqual => ast.Node.InfixOp.Op{ .AssignBitShiftRight = {} }, + Token.Id.AsteriskEqual => ast.Node.InfixOp.Op{ .AssignTimes = {} }, + Token.Id.AsteriskPercentEqual => ast.Node.InfixOp.Op{ .AssignTimesWarp = {} }, + Token.Id.CaretEqual => ast.Node.InfixOp.Op{ .AssignBitXor = {} }, + Token.Id.Equal => ast.Node.InfixOp.Op{ .Assign = {} }, + Token.Id.MinusEqual => ast.Node.InfixOp.Op{ .AssignMinus = {} }, + Token.Id.MinusPercentEqual => ast.Node.InfixOp.Op{ .AssignMinusWrap = {} }, + Token.Id.PercentEqual => ast.Node.InfixOp.Op{ .AssignMod = {} }, + Token.Id.PipeEqual => ast.Node.InfixOp.Op{ .AssignBitOr = {} }, + Token.Id.PlusEqual => ast.Node.InfixOp.Op{ .AssignPlus = {} }, + Token.Id.PlusPercentEqual => ast.Node.InfixOp.Op{ .AssignPlusWrap = {} }, + Token.Id.SlashEqual => ast.Node.InfixOp.Op{ .AssignDiv = {} }, else => null, }; } fn tokenIdToUnwrapExpr(id: @TagType(Token.Id)) ?ast.Node.InfixOp.Op { return switch (id) { - Token.Id.Keyword_catch => ast.Node.InfixOp.Op { .Catch = null }, - Token.Id.QuestionMarkQuestionMark => ast.Node.InfixOp.Op { .UnwrapMaybe = void{} }, + Token.Id.Keyword_catch => ast.Node.InfixOp.Op{ .Catch = null }, + Token.Id.QuestionMarkQuestionMark => ast.Node.InfixOp.Op{ .UnwrapMaybe = void{} }, else => null, }; } fn tokenIdToComparison(id: @TagType(Token.Id)) ?ast.Node.InfixOp.Op { return switch (id) { - Token.Id.BangEqual => ast.Node.InfixOp.Op { .BangEqual = void{} }, - Token.Id.EqualEqual => ast.Node.InfixOp.Op { .EqualEqual = void{} }, - Token.Id.AngleBracketLeft => ast.Node.InfixOp.Op { .LessThan = void{} }, - Token.Id.AngleBracketLeftEqual => ast.Node.InfixOp.Op { .LessOrEqual = void{} }, - Token.Id.AngleBracketRight => ast.Node.InfixOp.Op { .GreaterThan = void{} }, - Token.Id.AngleBracketRightEqual => ast.Node.InfixOp.Op { .GreaterOrEqual = void{} }, + Token.Id.BangEqual => ast.Node.InfixOp.Op{ .BangEqual = void{} }, + Token.Id.EqualEqual => ast.Node.InfixOp.Op{ .EqualEqual = void{} }, + Token.Id.AngleBracketLeft => ast.Node.InfixOp.Op{ .LessThan = void{} }, + Token.Id.AngleBracketLeftEqual => ast.Node.InfixOp.Op{ .LessOrEqual = void{} }, + Token.Id.AngleBracketRight => ast.Node.InfixOp.Op{ .GreaterThan = void{} }, + Token.Id.AngleBracketRightEqual => ast.Node.InfixOp.Op{ .GreaterOrEqual = void{} }, else => null, }; } fn tokenIdToBitShift(id: @TagType(Token.Id)) ?ast.Node.InfixOp.Op { return switch (id) { - Token.Id.AngleBracketAngleBracketLeft => ast.Node.InfixOp.Op { .BitShiftLeft = void{} }, - Token.Id.AngleBracketAngleBracketRight => ast.Node.InfixOp.Op { .BitShiftRight = void{} }, + Token.Id.AngleBracketAngleBracketLeft => ast.Node.InfixOp.Op{ .BitShiftLeft = void{} }, + Token.Id.AngleBracketAngleBracketRight => ast.Node.InfixOp.Op{ .BitShiftRight = void{} }, else => null, }; } fn tokenIdToAddition(id: @TagType(Token.Id)) ?ast.Node.InfixOp.Op { return switch (id) { - Token.Id.Minus => ast.Node.InfixOp.Op { .Sub = void{} }, - Token.Id.MinusPercent => ast.Node.InfixOp.Op { .SubWrap = void{} }, - Token.Id.Plus => ast.Node.InfixOp.Op { .Add = void{} }, - Token.Id.PlusPercent => ast.Node.InfixOp.Op { .AddWrap = void{} }, - Token.Id.PlusPlus => ast.Node.InfixOp.Op { .ArrayCat = void{} }, + Token.Id.Minus => ast.Node.InfixOp.Op{ .Sub = void{} }, + Token.Id.MinusPercent => ast.Node.InfixOp.Op{ .SubWrap = void{} }, + Token.Id.Plus => ast.Node.InfixOp.Op{ .Add = void{} }, + Token.Id.PlusPercent => ast.Node.InfixOp.Op{ .AddWrap = void{} }, + Token.Id.PlusPlus => ast.Node.InfixOp.Op{ .ArrayCat = void{} }, else => null, }; } fn tokenIdToMultiply(id: @TagType(Token.Id)) ?ast.Node.InfixOp.Op { return switch (id) { - Token.Id.Slash => ast.Node.InfixOp.Op { .Div = void{} }, - Token.Id.Asterisk => ast.Node.InfixOp.Op { .Mult = void{} }, - Token.Id.AsteriskAsterisk => ast.Node.InfixOp.Op { .ArrayMult = void{} }, - Token.Id.AsteriskPercent => ast.Node.InfixOp.Op { .MultWrap = void{} }, - Token.Id.Percent => ast.Node.InfixOp.Op { .Mod = void{} }, - Token.Id.PipePipe => ast.Node.InfixOp.Op { .MergeErrorSets = void{} }, + Token.Id.Slash => ast.Node.InfixOp.Op{ .Div = void{} }, + Token.Id.Asterisk => ast.Node.InfixOp.Op{ .Mult = void{} }, + Token.Id.AsteriskAsterisk => ast.Node.InfixOp.Op{ .ArrayMult = void{} }, + Token.Id.AsteriskPercent => ast.Node.InfixOp.Op{ .MultWrap = void{} }, + Token.Id.Percent => ast.Node.InfixOp.Op{ .Mod = void{} }, + Token.Id.PipePipe => ast.Node.InfixOp.Op{ .MergeErrorSets = void{} }, else => null, }; } fn tokenIdToPrefixOp(id: @TagType(Token.Id)) ?ast.Node.PrefixOp.Op { return switch (id) { - Token.Id.Bang => ast.Node.PrefixOp.Op { .BoolNot = void{} }, - Token.Id.Tilde => ast.Node.PrefixOp.Op { .BitNot = void{} }, - Token.Id.Minus => ast.Node.PrefixOp.Op { .Negation = void{} }, - Token.Id.MinusPercent => ast.Node.PrefixOp.Op { .NegationWrap = void{} }, - Token.Id.Asterisk, Token.Id.AsteriskAsterisk => ast.Node.PrefixOp.Op { .Deref = void{} }, - Token.Id.Ampersand => ast.Node.PrefixOp.Op { - .AddrOf = ast.Node.PrefixOp.AddrOfInfo { - .align_expr = null, - .bit_offset_start_token = null, - .bit_offset_end_token = null, - .const_token = null, - .volatile_token = null, - }, - }, - Token.Id.QuestionMark => ast.Node.PrefixOp.Op { .MaybeType = void{} }, - Token.Id.QuestionMarkQuestionMark => ast.Node.PrefixOp.Op { .UnwrapMaybe = void{} }, - Token.Id.Keyword_await => ast.Node.PrefixOp.Op { .Await = void{} }, - Token.Id.Keyword_try => ast.Node.PrefixOp.Op { .Try = void{ } }, + Token.Id.Bang => ast.Node.PrefixOp.Op{ .BoolNot = void{} }, + Token.Id.Tilde => ast.Node.PrefixOp.Op{ .BitNot = void{} }, + Token.Id.Minus => ast.Node.PrefixOp.Op{ .Negation = void{} }, + Token.Id.MinusPercent => ast.Node.PrefixOp.Op{ .NegationWrap = void{} }, + Token.Id.Asterisk, + Token.Id.AsteriskAsterisk => ast.Node.PrefixOp.Op{ .Deref = void{} }, + Token.Id.Ampersand => ast.Node.PrefixOp.Op{ .AddrOf = ast.Node.PrefixOp.AddrOfInfo{ + .align_expr = null, + .bit_offset_start_token = null, + .bit_offset_end_token = null, + .const_token = null, + .volatile_token = null, + } }, + Token.Id.QuestionMark => ast.Node.PrefixOp.Op{ .MaybeType = void{} }, + Token.Id.QuestionMarkQuestionMark => ast.Node.PrefixOp.Op{ .UnwrapMaybe = void{} }, + Token.Id.Keyword_await => ast.Node.PrefixOp.Op{ .Await = void{} }, + Token.Id.Keyword_try => ast.Node.PrefixOp.Op{ .Try = void{} }, else => null, }; } fn createLiteral(arena: &mem.Allocator, comptime T: type, token_index: TokenIndex) !&T { - return arena.construct(T { - .base = ast.Node {.id = ast.Node.typeToId(T)}, + return arena.construct(T{ + .base = ast.Node{ .id = ast.Node.typeToId(T) }, .token = token_index, }); } @@ -3389,15 +3159,14 @@ fn createToCtxLiteral(arena: &mem.Allocator, opt_ctx: &const OptionalCtx, compti fn eatToken(tok_it: &ast.Tree.TokenList.Iterator, tree: &ast.Tree, id: @TagType(Token.Id)) ?TokenIndex { const token = nextToken(tok_it, tree); - if (token.ptr.id == id) - return token.index; + if (token.ptr.id == id) return token.index; putBackToken(tok_it, tree); return null; } fn nextToken(tok_it: &ast.Tree.TokenList.Iterator, tree: &ast.Tree) AnnotatedToken { - const result = AnnotatedToken { + const result = AnnotatedToken{ .index = tok_it.index, .ptr = ??tok_it.next(), }; diff --git a/std/zig/render.zig b/std/zig/render.zig index 24a6566b5669489b26741494a5b5ec40366cf081..52bc074d5d892c243852537e4f58cb1eb81bb25a 100644 --- a/std/zig/render.zig +++ b/std/zig/render.zig @@ -7,7 +7,7 @@ const Token = std.zig.Token; const indent_delta = 4; -pub const Error = error { +pub const Error = error{ /// Ran out of memory allocating call stack frames to complete rendering. OutOfMemory, }; @@ -17,9 +17,9 @@ pub fn render(allocator: &mem.Allocator, stream: var, tree: &ast.Tree) (@typeOf( var it = tree.root_node.decls.iterator(0); while (it.next()) |decl| { - try renderTopLevelDecl(allocator, stream, tree, 0, *decl); + try renderTopLevelDecl(allocator, stream, tree, 0, decl.*); if (it.peek()) |next_decl| { - const n = if (nodeLineOffset(tree, *decl, *next_decl) >= 2) u8(2) else u8(1); + const n = if (nodeLineOffset(tree, decl.*, next_decl.*) >= 2) u8(2) else u8(1); try stream.writeByteNTimes('\n', n); } } @@ -154,10 +154,10 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind var it = block.statements.iterator(0); while (it.next()) |statement| { try stream.writeByteNTimes(' ', block_indent); - try renderStatement(allocator, stream, tree, block_indent, *statement); + try renderStatement(allocator, stream, tree, block_indent, statement.*); if (it.peek()) |next_statement| { - const n = if (nodeLineOffset(tree, *statement, *next_statement) >= 2) u8(2) else u8(1); + const n = if (nodeLineOffset(tree, statement.*, next_statement.*) >= 2) u8(2) else u8(1); try stream.writeByteNTimes('\n', n); } } @@ -203,7 +203,6 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind try stream.write(" "); try renderExpression(allocator, stream, tree, indent, body); } - }, ast.Node.Id.InfixOp => { @@ -335,7 +334,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind var it = call_info.params.iterator(0); while (it.next()) |param_node| { - try renderExpression(allocator, stream, tree, indent, *param_node); + try renderExpression(allocator, stream, tree, indent, param_node.*); if (it.peek() != null) { try stream.write(", "); } @@ -351,7 +350,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind try stream.write("]"); }, - ast.Node.SuffixOp.Op.SuffixOp { + ast.Node.SuffixOp.Op.SuffixOp => { try renderExpression(allocator, stream, tree, indent, suffix_op.lhs); try stream.write(".*"); }, @@ -375,7 +374,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind } if (field_inits.len == 1) { - const field_init = *field_inits.at(0); + const field_init = field_inits.at(0).*; try renderExpression(allocator, stream, tree, indent, suffix_op.lhs); try stream.write("{ "); @@ -392,12 +391,12 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind var it = field_inits.iterator(0); while (it.next()) |field_init| { try stream.writeByteNTimes(' ', new_indent); - try renderExpression(allocator, stream, tree, new_indent, *field_init); - if ((*field_init).id != ast.Node.Id.LineComment) { + try renderExpression(allocator, stream, tree, new_indent, field_init.*); + if ((field_init.*).id != ast.Node.Id.LineComment) { try stream.write(","); } if (it.peek()) |next_field_init| { - const n = if (nodeLineOffset(tree, *field_init, *next_field_init) >= 2) u8(2) else u8(1); + const n = if (nodeLineOffset(tree, field_init.*, next_field_init.*) >= 2) u8(2) else u8(1); try stream.writeByteNTimes('\n', n); } } @@ -408,14 +407,13 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind }, ast.Node.SuffixOp.Op.ArrayInitializer => |*exprs| { - if (exprs.len == 0) { try renderExpression(allocator, stream, tree, indent, suffix_op.lhs); try stream.write("{}"); return; } if (exprs.len == 1) { - const expr = *exprs.at(0); + const expr = exprs.at(0).*; try renderExpression(allocator, stream, tree, indent, suffix_op.lhs); try stream.write("{"); @@ -432,11 +430,11 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind var it = exprs.iterator(0); while (it.next()) |expr| { try stream.writeByteNTimes(' ', new_indent); - try renderExpression(allocator, stream, tree, new_indent, *expr); + try renderExpression(allocator, stream, tree, new_indent, expr.*); try stream.write(","); if (it.peek()) |next_expr| { - const n = if (nodeLineOffset(tree, *expr, *next_expr) >= 2) u8(2) else u8(1); + const n = if (nodeLineOffset(tree, expr.*, next_expr.*) >= 2) u8(2) else u8(1); try stream.writeByteNTimes('\n', n); } } @@ -469,7 +467,6 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind ast.Node.ControlFlowExpression.Kind.Return => { try stream.print("return"); }, - } if (flow_expr.rhs) |rhs| { @@ -575,7 +572,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind switch (container_decl.layout) { ast.Node.ContainerDecl.Layout.Packed => try stream.print("packed "), ast.Node.ContainerDecl.Layout.Extern => try stream.print("extern "), - ast.Node.ContainerDecl.Layout.Auto => { }, + ast.Node.ContainerDecl.Layout.Auto => {}, } switch (container_decl.kind) { @@ -611,10 +608,10 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind var it = container_decl.fields_and_decls.iterator(0); while (it.next()) |decl| { try stream.writeByteNTimes(' ', new_indent); - try renderTopLevelDecl(allocator, stream, tree, new_indent, *decl); + try renderTopLevelDecl(allocator, stream, tree, new_indent, decl.*); if (it.peek()) |next_decl| { - const n = if (nodeLineOffset(tree, *decl, *next_decl) >= 2) u8(2) else u8(1); + const n = if (nodeLineOffset(tree, decl.*, next_decl.*) >= 2) u8(2) else u8(1); try stream.writeByteNTimes('\n', n); } } @@ -634,7 +631,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind } if (err_set_decl.decls.len == 1) blk: { - const node = *err_set_decl.decls.at(0); + const node = err_set_decl.decls.at(0).*; // if there are any doc comments or same line comments // don't try to put it all on one line @@ -644,7 +641,6 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind break :blk; } - try stream.write("error{"); try renderTopLevelDecl(allocator, stream, tree, indent, node); try stream.write("}"); @@ -657,12 +653,12 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind var it = err_set_decl.decls.iterator(0); while (it.next()) |node| { try stream.writeByteNTimes(' ', new_indent); - try renderTopLevelDecl(allocator, stream, tree, new_indent, *node); - if ((*node).id != ast.Node.Id.LineComment) { + try renderTopLevelDecl(allocator, stream, tree, new_indent, node.*); + if ((node.*).id != ast.Node.Id.LineComment) { try stream.write(","); } if (it.peek()) |next_node| { - const n = if (nodeLineOffset(tree, *node, *next_node) >= 2) u8(2) else u8(1); + const n = if (nodeLineOffset(tree, node.*, next_node.*) >= 2) u8(2) else u8(1); try stream.writeByteNTimes('\n', n); } } @@ -676,9 +672,9 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind const multiline_str_literal = @fieldParentPtr(ast.Node.MultilineStringLiteral, "base", base); try stream.print("\n"); - var i : usize = 0; + var i: usize = 0; while (i < multiline_str_literal.lines.len) : (i += 1) { - const t = *multiline_str_literal.lines.at(i); + const t = multiline_str_literal.lines.at(i).*; try stream.writeByteNTimes(' ', indent + indent_delta); try stream.print("{}", tree.tokenSlice(t)); } @@ -695,7 +691,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind var it = builtin_call.params.iterator(0); while (it.next()) |param_node| { - try renderExpression(allocator, stream, tree, indent, *param_node); + try renderExpression(allocator, stream, tree, indent, param_node.*); if (it.peek() != null) { try stream.write(", "); } @@ -740,7 +736,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind var it = fn_proto.params.iterator(0); while (it.next()) |param_decl_node| { - try renderParamDecl(allocator, stream, tree, indent, *param_decl_node); + try renderParamDecl(allocator, stream, tree, indent, param_decl_node.*); if (it.peek() != null) { try stream.write(", "); @@ -764,7 +760,6 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind try renderExpression(allocator, stream, tree, indent, node); }, } - }, ast.Node.Id.PromiseType => { @@ -801,10 +796,10 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind var it = switch_node.cases.iterator(0); while (it.next()) |node| { try stream.writeByteNTimes(' ', new_indent); - try renderExpression(allocator, stream, tree, new_indent, *node); + try renderExpression(allocator, stream, tree, new_indent, node.*); if (it.peek()) |next_node| { - const n = if (nodeLineOffset(tree, *node, *next_node) >= 2) u8(2) else u8(1); + const n = if (nodeLineOffset(tree, node.*, next_node.*) >= 2) u8(2) else u8(1); try stream.writeByteNTimes('\n', n); } } @@ -819,7 +814,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind var it = switch_case.items.iterator(0); while (it.next()) |node| { - try renderExpression(allocator, stream, tree, indent, *node); + try renderExpression(allocator, stream, tree, indent, node.*); if (it.peek() != null) { try stream.write(",\n"); @@ -846,8 +841,10 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind try stream.print("{}", tree.tokenSlice(else_node.else_token)); const block_body = switch (else_node.body.id) { - ast.Node.Id.Block, ast.Node.Id.If, - ast.Node.Id.For, ast.Node.Id.While, + ast.Node.Id.Block, + ast.Node.Id.If, + ast.Node.Id.For, + ast.Node.Id.While, ast.Node.Id.Switch => true, else => false, }; @@ -972,7 +969,11 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind try renderExpression(allocator, stream, tree, indent, if_node.body); switch (if_node.body.id) { - ast.Node.Id.Block, ast.Node.Id.If, ast.Node.Id.For, ast.Node.Id.While, ast.Node.Id.Switch => { + ast.Node.Id.Block, + ast.Node.Id.If, + ast.Node.Id.For, + ast.Node.Id.While, + ast.Node.Id.Switch => { if (if_node.@"else") |@"else"| { if (if_node.body.id == ast.Node.Id.Block) { try stream.write(" "); @@ -995,7 +996,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind try renderExpression(allocator, stream, tree, indent, @"else".body); } - } + }, } }, @@ -1018,11 +1019,11 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind { var it = asm_node.outputs.iterator(0); while (it.next()) |asm_output| { - const node = &(*asm_output).base; + const node = &(asm_output.*).base; try renderExpression(allocator, stream, tree, indent_extra, node); if (it.peek()) |next_asm_output| { - const next_node = &(*next_asm_output).base; + const next_node = &(next_asm_output.*).base; const n = if (nodeLineOffset(tree, node, next_node) >= 2) u8(2) else u8(1); try stream.writeByte(','); try stream.writeByteNTimes('\n', n); @@ -1038,11 +1039,11 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind { var it = asm_node.inputs.iterator(0); while (it.next()) |asm_input| { - const node = &(*asm_input).base; + const node = &(asm_input.*).base; try renderExpression(allocator, stream, tree, indent_extra, node); if (it.peek()) |next_asm_input| { - const next_node = &(*next_asm_input).base; + const next_node = &(next_asm_input.*).base; const n = if (nodeLineOffset(tree, node, next_node) >= 2) u8(2) else u8(1); try stream.writeByte(','); try stream.writeByteNTimes('\n', n); @@ -1058,7 +1059,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind { var it = asm_node.clobbers.iterator(0); while (it.next()) |node| { - try renderExpression(allocator, stream, tree, indent_once, *node); + try renderExpression(allocator, stream, tree, indent_once, node.*); if (it.peek() != null) { try stream.write(", "); @@ -1220,8 +1221,7 @@ fn renderComments(tree: &ast.Tree, stream: var, node: var, indent: usize) (@type const comment = node.doc_comments ?? return; var it = comment.lines.iterator(0); while (it.next()) |line_token_index| { - try stream.print("{}\n", tree.tokenSlice(*line_token_index)); + try stream.print("{}\n", tree.tokenSlice(line_token_index.*)); try stream.writeByteNTimes(' ', indent); } } - -- 2.54.0 From 4a3d689550286fbf7859321991c8f7b7e6d87207 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 16 May 2018 18:22:39 -0400 Subject: [PATCH 21/47] std.fmt: use SI prefixes for printing bytes closes #1015 --- std/fmt/index.zig | 87 +++++++++++++++++++++++++++++++---------------- 1 file changed, 58 insertions(+), 29 deletions(-) diff --git a/std/fmt/index.zig b/std/fmt/index.zig index e26b2f6c8bcd1dc2d9f798445a9e7681488a92fa..9170acbe89ccd7eaa70d29bc1c61cf49f68789bf 100644 --- a/std/fmt/index.zig +++ b/std/fmt/index.zig @@ -28,6 +28,7 @@ pub fn format(context: var, comptime Errors: type, output: fn(@typeOf(context), Buf, BufWidth, Bytes, + BytesBase, BytesWidth, }; @@ -99,6 +100,7 @@ pub fn format(context: var, comptime Errors: type, output: fn(@typeOf(context), }, 'B' => { width = 0; + radix = 1000; state = State.Bytes; }, else => @compileError("Unknown format character: " ++ []u8{c}), @@ -214,7 +216,24 @@ pub fn format(context: var, comptime Errors: type, output: fn(@typeOf(context), }, State.Bytes => switch (c) { '}' => { - try formatBytes(args[next_arg], 0, context, Errors, output); + try formatBytes(args[next_arg], 0, radix, context, Errors, output); + next_arg += 1; + state = State.Start; + start_index = i + 1; + }, + 'i' => { + radix = 1024; + state = State.BytesBase; + }, + '0' ... '9' => { + width_start = i; + state = State.BytesWidth; + }, + else => @compileError("Unexpected character in format string: " ++ []u8{c}), + }, + State.BytesBase => switch (c) { + '}' => { + try formatBytes(args[next_arg], 0, radix, context, Errors, output); next_arg += 1; state = State.Start; start_index = i + 1; @@ -228,7 +247,7 @@ pub fn format(context: var, comptime Errors: type, output: fn(@typeOf(context), State.BytesWidth => switch (c) { '}' => { width = comptime (parseUnsigned(usize, fmt[width_start..i], 10) catch unreachable); - try formatBytes(args[next_arg], width, context, Errors, output); + try formatBytes(args[next_arg], width, radix, context, Errors, output); next_arg += 1; state = State.Start; start_index = i + 1; @@ -550,7 +569,7 @@ pub fn formatFloatDecimal(value: var, maybe_precision: ?usize, context: var, com } } -pub fn formatBytes(value: var, width: ?usize, +pub fn formatBytes(value: var, width: ?usize, comptime radix: usize, context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8)Errors!void) Errors!void { if (value == 0) { @@ -558,16 +577,26 @@ pub fn formatBytes(value: var, width: ?usize, } const mags = " KMGTPEZY"; - const magnitude = math.min(math.log2(value) / 10, mags.len - 1); - const new_value = f64(value) / math.pow(f64, 1024, f64(magnitude)); + const magnitude = switch (radix) { + 1000 => math.min(math.log2(value) / comptime math.log2(1000), mags.len - 1), + 1024 => math.min(math.log2(value) / 10, mags.len - 1), + else => unreachable, + }; + const new_value = f64(value) / math.pow(f64, f64(radix), f64(magnitude)); const suffix = mags[magnitude]; try formatFloatDecimal(new_value, width, context, Errors, output); - if (suffix != ' ') { - try output(context, (&suffix)[0..1]); + if (suffix == ' ') { + return output(context, "B"); } - return output(context, "B"); + + const buf = switch (radix) { + 1000 => []u8 { suffix, 'B' }, + 1024 => []u8 { suffix, 'i', 'B' }, + else => unreachable, + }; + return output(context, buf); } pub fn formatInt(value: var, base: u8, uppercase: bool, width: usize, @@ -787,41 +816,27 @@ test "parse unsigned comptime" { test "fmt.format" { { - var buf1: [32]u8 = undefined; const value: ?i32 = 1234; - const result = try bufPrint(buf1[0..], "nullable: {}\n", value); - assert(mem.eql(u8, result, "nullable: 1234\n")); + try testFmt("nullable: 1234\n", "nullable: {}\n", value); } { - var buf1: [32]u8 = undefined; const value: ?i32 = null; - const result = try bufPrint(buf1[0..], "nullable: {}\n", value); - assert(mem.eql(u8, result, "nullable: null\n")); + try testFmt("nullable: null\n", "nullable: {}\n", value); } { - var buf1: [32]u8 = undefined; const value: error!i32 = 1234; - const result = try bufPrint(buf1[0..], "error union: {}\n", value); - assert(mem.eql(u8, result, "error union: 1234\n")); + try testFmt("error union: 1234\n", "error union: {}\n", value); } { - var buf1: [32]u8 = undefined; const value: error!i32 = error.InvalidChar; - const result = try bufPrint(buf1[0..], "error union: {}\n", value); - assert(mem.eql(u8, result, "error union: error.InvalidChar\n")); + try testFmt("error union: error.InvalidChar\n", "error union: {}\n", value); } { - var buf1: [32]u8 = undefined; const value: u3 = 0b101; - const result = try bufPrint(buf1[0..], "u3: {}\n", value); - assert(mem.eql(u8, result, "u3: 5\n")); - } - { - var buf1: [32]u8 = undefined; - const value: usize = 63 * 1024 * 1024; - const result = try bufPrint(buf1[0..], "file size: {B}\n", value); - assert(mem.eql(u8, result, "file size: 63MB\n")); + try testFmt("u3: 5\n", "u3: {}\n", value); } + try testFmt("file size: 63MiB\n", "file size: {Bi}\n", usize(63 * 1024 * 1024)); + try testFmt("file size: 66.06MB\n", "file size: {B2}\n", usize(63 * 1024 * 1024)); { // Dummy field because of https://github.com/zig-lang/zig/issues/557. const Struct = struct { @@ -1041,6 +1056,20 @@ test "fmt.format" { } } +fn testFmt(expected: []const u8, comptime template: []const u8, args: ...) !void { + var buf: [100]u8 = undefined; + const result = try bufPrint(buf[0..], template, args); + if (mem.eql(u8, result, expected)) + return; + + std.debug.warn("\n====== expected this output: =========\n"); + std.debug.warn("{}", expected); + std.debug.warn("\n======== instead found this: =========\n"); + std.debug.warn("{}", result); + std.debug.warn("\n======================================\n"); + return error.TestFailed; +} + pub fn trim(buf: []const u8) []const u8 { var start: usize = 0; while (start < buf.len and isWhiteSpace(buf[start])) : (start += 1) { } -- 2.54.0 From 967bad43a053bf7d9d54dd352fcd8416c767785e Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 16 May 2018 20:18:38 -0400 Subject: [PATCH 22/47] OpenBSD has the same C integer sizes as Linux Thanks Jan S for this information closes #1016 --- src/target.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/target.cpp b/src/target.cpp index 57970888fcee76c64e4172d102b750897ec6df17..c53ed74d145759bebe161d6126ef923e95f63b62 100644 --- a/src/target.cpp +++ b/src/target.cpp @@ -702,6 +702,7 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) { case OsLinux: case OsMacOSX: case OsZen: + case OsOpenBSD: switch (id) { case CIntTypeShort: case CIntTypeUShort: @@ -742,7 +743,6 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) { case OsKFreeBSD: case OsLv2: case OsNetBSD: - case OsOpenBSD: case OsSolaris: case OsHaiku: case OsMinix: -- 2.54.0 From 9ea0e4ca6803cd10cfbffbdf80033a90f0e544d5 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 17 May 2018 00:15:52 -0400 Subject: [PATCH 23/47] zig fmt: same line comments after tokens in expression --- std/zig/parser_test.zig | 43 +++++++++++++++++++++++++++++++++++++++++ std/zig/render.zig | 41 +++++++++++++++++++++++---------------- 2 files changed, 67 insertions(+), 17 deletions(-) diff --git a/std/zig/parser_test.zig b/std/zig/parser_test.zig index 129e62e6dda8bc1078f8925edceb98a6e67bfa40..ea26f823b5df3c5c8bfc757f39549edff2808709 100644 --- a/std/zig/parser_test.zig +++ b/std/zig/parser_test.zig @@ -1,3 +1,46 @@ +test "zig fmt: same line comments in expression" { + try testCanonical( + \\test "aoeu" { + \\ const x = ( // a + \\ 0 // b + \\ ); // c + \\} + \\ + ); +} + +//test "zig fmt: line comment between if block and else keyword" { +// try testTransform( +// test "aoeu" { +// // cexp(finite|nan +- i inf|nan) = nan + i nan +// if ((hx & 0x7fffffff) != 0x7f800000) { +// return Complex(f32).new(y - y, y - y); +// } +// // cexp(-inf +- i inf|nan) = 0 + i0 +// else if (hx & 0x80000000 != 0) { +// return Complex(f32).new(0, 0); +// } +// // cexp(+inf +- i inf|nan) = inf + i nan +// else { +// return Complex(f32).new(x, y - y); +// } +// } +// , +// test "aoeu" { +// // cexp(finite|nan +- i inf|nan) = nan + i nan +// if ((hx & 0x7fffffff) != 0x7f800000) { +// return Complex(f32).new(y - y, y - y); +// } // cexp(-inf +- i inf|nan) = 0 + i0 +// else if (hx & 0x80000000 != 0) { +// return Complex(f32).new(0, 0); +// } // cexp(+inf +- i inf|nan) = inf + i nan +// else { +// return Complex(f32).new(x, y - y); +// } +// } +// ); +//} + test "zig fmt: add comma on last switch prong" { try testTransform( \\test "aoeu" { diff --git a/std/zig/render.zig b/std/zig/render.zig index 5084c1d096d78ca6a7e45fd7ba2706b975481d19..9ce8ba0cbfd6f534ad04aea4d0bddd2fa8a5eae7 100644 --- a/std/zig/render.zig +++ b/std/zig/render.zig @@ -81,7 +81,7 @@ fn renderTopLevelDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, i } try stream.print("{}: ", tree.tokenSlice(field.name_token)); try renderExpression(allocator, stream, tree, indent, field.type_expr); - try renderToken(tree, stream, field.lastToken() + 1, indent, true); + try renderToken(tree, stream, field.lastToken() + 1, indent, true, true); }, ast.Node.Id.UnionTag => { const tag = @fieldParentPtr(ast.Node.UnionTag, "base", decl); @@ -513,9 +513,9 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind ast.Node.Id.GroupedExpression => { const grouped_expr = @fieldParentPtr(ast.Node.GroupedExpression, "base", base); - try stream.write("("); + try renderToken(tree, stream, grouped_expr.lparen, indent, false, false); try renderExpression(allocator, stream, tree, indent, grouped_expr.expr); - try stream.write(")"); + try renderToken(tree, stream, grouped_expr.rparen, indent, false, false); }, ast.Node.Id.FieldInitializer => { @@ -527,7 +527,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind ast.Node.Id.IntegerLiteral => { const integer_literal = @fieldParentPtr(ast.Node.IntegerLiteral, "base", base); - try stream.print("{}", tree.tokenSlice(integer_literal.token)); + try renderToken(tree, stream, integer_literal.token, indent, false, false); }, ast.Node.Id.FloatLiteral => { const float_literal = @fieldParentPtr(ast.Node.FloatLiteral, "base", base); @@ -535,7 +535,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind }, ast.Node.Id.StringLiteral => { const string_literal = @fieldParentPtr(ast.Node.StringLiteral, "base", base); - try stream.print("{}", tree.tokenSlice(string_literal.token)); + try renderToken(tree, stream, string_literal.token, indent, false, false); }, ast.Node.Id.CharLiteral => { const char_literal = @fieldParentPtr(ast.Node.CharLiteral, "base", base); @@ -840,9 +840,9 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind }, Token.Id.LineComment => { try stream.write(", "); - try renderToken(tree, stream, index, indent, true); + try renderToken(tree, stream, index, indent, true, true); }, - else => try renderToken(tree, stream, index, indent, true), + else => try renderToken(tree, stream, index, indent, true, true), } } }, @@ -971,7 +971,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind try stream.print("{} (", tree.tokenSlice(if_node.if_token)); try renderExpression(allocator, stream, tree, indent, if_node.condition); - try renderToken(tree, stream, if_node.condition.lastToken() + 1, indent, false); + try renderToken(tree, stream, if_node.condition.lastToken() + 1, indent, false, true); if (if_node.payload) |payload| { try renderExpression(allocator, stream, tree, indent, payload); @@ -1126,11 +1126,11 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind fn renderVarDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent: usize, var_decl: &ast.Node.VarDecl) (@typeOf(stream).Child.Error || Error)!void { if (var_decl.visib_token) |visib_token| { - try stream.print("{} ", tree.tokenSlice(visib_token)); + try renderToken(tree, stream, visib_token, indent, false, true); } if (var_decl.extern_export_token) |extern_export_token| { - try stream.print("{} ", tree.tokenSlice(extern_export_token)); + try renderToken(tree, stream, extern_export_token, indent, false, true); if (var_decl.lib_name) |lib_name| { try renderExpression(allocator, stream, tree, indent, lib_name); @@ -1139,10 +1139,11 @@ fn renderVarDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent } if (var_decl.comptime_token) |comptime_token| { - try stream.print("{} ", tree.tokenSlice(comptime_token)); + try renderToken(tree, stream, comptime_token, indent, false, true); } - try stream.print("{} {}", tree.tokenSlice(var_decl.mut_token), tree.tokenSlice(var_decl.name_token)); + try renderToken(tree, stream, var_decl.mut_token, indent, false, true); + try renderToken(tree, stream, var_decl.name_token, indent, false, false); if (var_decl.type_node) |type_node| { try stream.write(": "); @@ -1161,14 +1162,14 @@ fn renderVarDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent try renderExpression(allocator, stream, tree, indent, init_node); } - try renderToken(tree, stream, var_decl.semicolon_token, indent, true); + try renderToken(tree, stream, var_decl.semicolon_token, indent, true, false); } fn maybeRenderSemicolon(stream: var, tree: &ast.Tree, indent: usize, base: &ast.Node) (@typeOf(stream).Child.Error || Error)!void { if (base.requireSemiColon()) { const semicolon_index = base.lastToken() + 1; assert(tree.tokens.at(semicolon_index).id == Token.Id.Semicolon); - try renderToken(tree, stream, semicolon_index, indent, true); + try renderToken(tree, stream, semicolon_index, indent, true, true); } } @@ -1203,7 +1204,7 @@ fn renderStatement(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, inde } } -fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent: usize, line_break: bool) (@typeOf(stream).Child.Error || Error)!void { +fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent: usize, line_break: bool, space: bool) (@typeOf(stream).Child.Error || Error)!void { const token = tree.tokens.at(token_index); try stream.write(tree.tokenSlicePtr(token)); @@ -1214,13 +1215,19 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent try stream.print(" {}", tree.tokenSlicePtr(next_token)); if (!line_break) { try stream.write("\n"); - try stream.writeByteNTimes(' ', indent + indent_delta); + + const after_comment_token = tree.tokens.at(token_index + 2); + const next_line_indent = switch (after_comment_token.id) { + Token.Id.RParen, Token.Id.RBrace, Token.Id.RBracket => indent, + else => indent + indent_delta, + }; + try stream.writeByteNTimes(' ', next_line_indent); return; } } } - if (!line_break) { + if (!line_break and space) { try stream.writeByte(' '); } } -- 2.54.0 From 37c6afa5b4c25e008206d8a036e02b7fd7189459 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 17 May 2018 00:31:47 -0400 Subject: [PATCH 24/47] zig fmt: line comment between if block and else keyword --- std/zig/parse.zig | 1 + std/zig/parser_test.zig | 67 +++++++++++++++++++++-------------------- std/zig/render.zig | 9 ++++++ 3 files changed, 45 insertions(+), 32 deletions(-) diff --git a/std/zig/parse.zig b/std/zig/parse.zig index 4f1e3dcefeb40e71dc68ee5aeedc824b4e458a6d..094d368c23e207112052168cf1a0f6710890c4cc 100644 --- a/std/zig/parse.zig +++ b/std/zig/parse.zig @@ -1017,6 +1017,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { continue; }, State.Else => |dest| { + while (try eatLineComment(arena, &tok_it, &tree)) |_| { } if (eatToken(&tok_it, &tree, Token.Id.Keyword_else)) |else_token| { const node = try arena.construct(ast.Node.Else { .base = ast.Node {.id = ast.Node.Id.Else }, diff --git a/std/zig/parser_test.zig b/std/zig/parser_test.zig index ea26f823b5df3c5c8bfc757f39549edff2808709..38e61fe8fe2afc96535684d4a5875cdac837c3a7 100644 --- a/std/zig/parser_test.zig +++ b/std/zig/parser_test.zig @@ -1,3 +1,38 @@ +test "zig fmt: line comment between if block and else keyword" { + try testTransform( + \\test "aoeu" { + \\ // cexp(finite|nan +- i inf|nan) = nan + i nan + \\ if ((hx & 0x7fffffff) != 0x7f800000) { + \\ return Complex(f32).new(y - y, y - y); + \\ } + \\ // cexp(-inf +- i inf|nan) = 0 + i0 + \\ else if (hx & 0x80000000 != 0) { + \\ return Complex(f32).new(0, 0); + \\ } + \\ // cexp(+inf +- i inf|nan) = inf + i nan + \\ // another comment + \\ else { + \\ return Complex(f32).new(x, y - y); + \\ } + \\} + , + \\test "aoeu" { + \\ // cexp(finite|nan +- i inf|nan) = nan + i nan + \\ if ((hx & 0x7fffffff) != 0x7f800000) { + \\ return Complex(f32).new(y - y, y - y); + \\ } // cexp(-inf +- i inf|nan) = 0 + i0 + \\ else if (hx & 0x80000000 != 0) { + \\ return Complex(f32).new(0, 0); + \\ } // cexp(+inf +- i inf|nan) = inf + i nan + \\ // another comment + \\ else { + \\ return Complex(f32).new(x, y - y); + \\ } + \\} + \\ + ); +} + test "zig fmt: same line comments in expression" { try testCanonical( \\test "aoeu" { @@ -9,38 +44,6 @@ test "zig fmt: same line comments in expression" { ); } -//test "zig fmt: line comment between if block and else keyword" { -// try testTransform( -// test "aoeu" { -// // cexp(finite|nan +- i inf|nan) = nan + i nan -// if ((hx & 0x7fffffff) != 0x7f800000) { -// return Complex(f32).new(y - y, y - y); -// } -// // cexp(-inf +- i inf|nan) = 0 + i0 -// else if (hx & 0x80000000 != 0) { -// return Complex(f32).new(0, 0); -// } -// // cexp(+inf +- i inf|nan) = inf + i nan -// else { -// return Complex(f32).new(x, y - y); -// } -// } -// , -// test "aoeu" { -// // cexp(finite|nan +- i inf|nan) = nan + i nan -// if ((hx & 0x7fffffff) != 0x7f800000) { -// return Complex(f32).new(y - y, y - y); -// } // cexp(-inf +- i inf|nan) = 0 + i0 -// else if (hx & 0x80000000 != 0) { -// return Complex(f32).new(0, 0); -// } // cexp(+inf +- i inf|nan) = inf + i nan -// else { -// return Complex(f32).new(x, y - y); -// } -// } -// ); -//} - test "zig fmt: add comma on last switch prong" { try testTransform( \\test "aoeu" { diff --git a/std/zig/render.zig b/std/zig/render.zig index 9ce8ba0cbfd6f534ad04aea4d0bddd2fa8a5eae7..980addc77a779fb99eb35b12118c1bacad80f472 100644 --- a/std/zig/render.zig +++ b/std/zig/render.zig @@ -852,6 +852,15 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind }, ast.Node.Id.Else => { const else_node = @fieldParentPtr(ast.Node.Else, "base", base); + + var prev_tok_index = else_node.else_token - 1; + while (tree.tokens.at(prev_tok_index).id == Token.Id.LineComment) : (prev_tok_index -= 1) { } + prev_tok_index += 1; + while (prev_tok_index < else_node.else_token) : (prev_tok_index += 1) { + try stream.print("{}\n", tree.tokenSlice(prev_tok_index)); + try stream.writeByteNTimes(' ', indent); + } + try stream.print("{}", tree.tokenSlice(else_node.else_token)); const block_body = switch (else_node.body.id) { -- 2.54.0 From b48d354600406d39b29fe7327b09a62d2584a83f Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 17 May 2018 00:44:55 -0400 Subject: [PATCH 25/47] zig fmt: fix comment after if before another if --- std/segmented_list.zig | 18 ++++++++++++------ std/zig/parse.zig | 9 ++++++++- std/zig/parser_test.zig | 15 +++++++++++++++ 3 files changed, 35 insertions(+), 7 deletions(-) diff --git a/std/segmented_list.zig b/std/segmented_list.zig index a89d332556e90a317cf617f6babb59a57d50a316..977a7250334251c5c5619f03208a901ff7f7e5b3 100644 --- a/std/segmented_list.zig +++ b/std/segmented_list.zig @@ -298,21 +298,27 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type return &it.list.dynamic_segments[it.shelf_index][it.box_index]; } + + pub fn set(it: &Iterator, index: usize) void { + if (index < prealloc_item_count) { + it.index = index; + return; + } + it.shelf_index = shelfIndex(index); + it.box_index = boxIndex(index, it.shelf_index); + it.shelf_size = shelfSize(it.shelf_index); + } }; pub fn iterator(self: &Self, start_index: usize) Iterator { var it = Iterator { .list = self, - .index = start_index, + .index = undefined, .shelf_index = undefined, .box_index = undefined, .shelf_size = undefined, }; - if (start_index >= prealloc_item_count) { - it.shelf_index = shelfIndex(start_index); - it.box_index = boxIndex(start_index, it.shelf_index); - it.shelf_size = shelfSize(it.shelf_index); - } + it.set(start_index); return it; } }; diff --git a/std/zig/parse.zig b/std/zig/parse.zig index 094d368c23e207112052168cf1a0f6710890c4cc..970c49c4b296256bc417030cd4a51e351db7e216 100644 --- a/std/zig/parse.zig +++ b/std/zig/parse.zig @@ -1017,7 +1017,11 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { continue; }, State.Else => |dest| { - while (try eatLineComment(arena, &tok_it, &tree)) |_| { } + const old_index = tok_it.index; + var need_index_restore = false; + while (try eatLineComment(arena, &tok_it, &tree)) |_| { + need_index_restore = true; + } if (eatToken(&tok_it, &tree, Token.Id.Keyword_else)) |else_token| { const node = try arena.construct(ast.Node.Else { .base = ast.Node {.id = ast.Node.Id.Else }, @@ -1031,6 +1035,9 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { try stack.append(State { .Payload = OptionalCtx { .Optional = &node.payload } }); continue; } else { + if (need_index_restore) { + tok_it.set(old_index); + } continue; } }, diff --git a/std/zig/parser_test.zig b/std/zig/parser_test.zig index 38e61fe8fe2afc96535684d4a5875cdac837c3a7..094c4d51f721d1e677b5a62058a3ae30649e308c 100644 --- a/std/zig/parser_test.zig +++ b/std/zig/parser_test.zig @@ -1,3 +1,18 @@ +test "zig fmt: comment after if before another if" { + try testCanonical( + \\test "aoeu" { + \\ if (x) { + \\ foo(); + \\ } + \\ // comment + \\ if (x) { + \\ bar(); + \\ } + \\} + \\ + ); +} + test "zig fmt: line comment between if block and else keyword" { try testTransform( \\test "aoeu" { -- 2.54.0 From 942d384831196acf24868c32ef84409b05441960 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 17 May 2018 00:52:36 -0400 Subject: [PATCH 26/47] fix std.SegmentedList.Iterator.set --- std/segmented_list.zig | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/std/segmented_list.zig b/std/segmented_list.zig index 977a7250334251c5c5619f03208a901ff7f7e5b3..b324c6c4bdc6103174c75790fb30fc761c99bf2b 100644 --- a/std/segmented_list.zig +++ b/std/segmented_list.zig @@ -300,10 +300,8 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type } pub fn set(it: &Iterator, index: usize) void { - if (index < prealloc_item_count) { - it.index = index; - return; - } + it.index = index; + if (index < prealloc_item_count) return; it.shelf_index = shelfIndex(index); it.box_index = boxIndex(index, it.shelf_index); it.shelf_size = shelfSize(it.shelf_index); -- 2.54.0 From b73307befb49dd3b131d99ecf1c7f3fb54578ec8 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 17 May 2018 00:56:14 -0400 Subject: [PATCH 27/47] more std lib to postfix deref with zig fmt --- std/math/complex/exp.zig | 28 +++++++++++----------------- std/math/complex/ldexp.zig | 17 +++++++---------- 2 files changed, 18 insertions(+), 27 deletions(-) diff --git a/std/math/complex/exp.zig b/std/math/complex/exp.zig index 03f7f9e41ba2efacd76554c181fe919f4fdad43f..8fe069a43d607263d51f03b86fcd15c0f065a966 100644 --- a/std/math/complex/exp.zig +++ b/std/math/complex/exp.zig @@ -19,8 +19,8 @@ pub fn exp(z: var) Complex(@typeOf(z.re)) { fn exp32(z: &const Complex(f32)) Complex(f32) { @setFloatMode(this, @import("builtin").FloatMode.Strict); - const exp_overflow = 0x42b17218; // max_exp * ln2 ~= 88.72283955 - const cexp_overflow = 0x43400074; // (max_exp - min_denom_exp) * ln2 + const exp_overflow = 0x42b17218; // max_exp * ln2 ~= 88.72283955 + const cexp_overflow = 0x43400074; // (max_exp - min_denom_exp) * ln2 const x = z.re; const y = z.im; @@ -41,12 +41,10 @@ fn exp32(z: &const Complex(f32)) Complex(f32) { // cexp(finite|nan +- i inf|nan) = nan + i nan if ((hx & 0x7fffffff) != 0x7f800000) { return Complex(f32).new(y - y, y - y); - } - // cexp(-inf +- i inf|nan) = 0 + i0 + } // cexp(-inf +- i inf|nan) = 0 + i0 else if (hx & 0x80000000 != 0) { return Complex(f32).new(0, 0); - } - // cexp(+inf +- i inf|nan) = inf + i nan + } // cexp(+inf +- i inf|nan) = inf + i nan else { return Complex(f32).new(x, y - y); } @@ -55,8 +53,7 @@ fn exp32(z: &const Complex(f32)) Complex(f32) { // 88.7 <= x <= 192 so must scale if (hx >= exp_overflow and hx <= cexp_overflow) { return ldexp_cexp(z, 0); - } - // - x < exp_overflow => exp(x) won't overflow (common) + } // - x < exp_overflow => exp(x) won't overflow (common) // - x > cexp_overflow, so exp(x) * s overflows for s > 0 // - x = +-inf // - x = nan @@ -67,8 +64,8 @@ fn exp32(z: &const Complex(f32)) Complex(f32) { } fn exp64(z: &const Complex(f64)) Complex(f64) { - const exp_overflow = 0x40862e42; // high bits of max_exp * ln2 ~= 710 - const cexp_overflow = 0x4096b8e4; // (max_exp - min_denorm_exp) * ln2 + const exp_overflow = 0x40862e42; // high bits of max_exp * ln2 ~= 710 + const cexp_overflow = 0x4096b8e4; // (max_exp - min_denorm_exp) * ln2 const x = z.re; const y = z.im; @@ -95,12 +92,10 @@ fn exp64(z: &const Complex(f64)) Complex(f64) { // cexp(finite|nan +- i inf|nan) = nan + i nan if (lx != 0 or (hx & 0x7fffffff) != 0x7ff00000) { return Complex(f64).new(y - y, y - y); - } - // cexp(-inf +- i inf|nan) = 0 + i0 + } // cexp(-inf +- i inf|nan) = 0 + i0 else if (hx & 0x80000000 != 0) { return Complex(f64).new(0, 0); - } - // cexp(+inf +- i inf|nan) = inf + i nan + } // cexp(+inf +- i inf|nan) = inf + i nan else { return Complex(f64).new(x, y - y); } @@ -109,9 +104,8 @@ fn exp64(z: &const Complex(f64)) Complex(f64) { // 709.7 <= x <= 1454.3 so must scale if (hx >= exp_overflow and hx <= cexp_overflow) { const r = ldexp_cexp(z, 0); - return *r; - } - // - x < exp_overflow => exp(x) won't overflow (common) + return r.*; + } // - x < exp_overflow => exp(x) won't overflow (common) // - x > cexp_overflow, so exp(x) * s overflows for s > 0 // - x = +-inf // - x = nan diff --git a/std/math/complex/ldexp.zig b/std/math/complex/ldexp.zig index 4fb5a6815fde4d1a74a8c131e53e3822e3c450c0..7ebefff40c77cc7ab837aba9261db954a315a4c2 100644 --- a/std/math/complex/ldexp.zig +++ b/std/math/complex/ldexp.zig @@ -15,12 +15,12 @@ pub fn ldexp_cexp(z: var, expt: i32) Complex(@typeOf(z.re)) { } fn frexp_exp32(x: f32, expt: &i32) f32 { - const k = 235; // reduction constant - const kln2 = 162.88958740; // k * ln2 + const k = 235; // reduction constant + const kln2 = 162.88958740; // k * ln2 const exp_x = math.exp(x - kln2); const hx = @bitCast(u32, exp_x); - *expt = i32(hx >> 23) - (0x7f + 127) + k; + expt.* = i32(hx >> 23) - (0x7f + 127) + k; return @bitCast(f32, (hx & 0x7fffff) | ((0x7f + 127) << 23)); } @@ -35,15 +35,12 @@ fn ldexp_cexp32(z: &const Complex(f32), expt: i32) Complex(f32) { const half_expt2 = exptf - half_expt1; const scale2 = @bitCast(f32, (0x7f + half_expt2) << 23); - return Complex(f32).new( - math.cos(z.im) * exp_x * scale1 * scale2, - math.sin(z.im) * exp_x * scale1 * scale2, - ); + return Complex(f32).new(math.cos(z.im) * exp_x * scale1 * scale2, math.sin(z.im) * exp_x * scale1 * scale2); } fn frexp_exp64(x: f64, expt: &i32) f64 { - const k = 1799; // reduction constant - const kln2 = 1246.97177782734161156; // k * ln2 + const k = 1799; // reduction constant + const kln2 = 1246.97177782734161156; // k * ln2 const exp_x = math.exp(x - kln2); @@ -51,7 +48,7 @@ fn frexp_exp64(x: f64, expt: &i32) f64 { const hx = u32(fx >> 32); const lx = @truncate(u32, fx); - *expt = i32(hx >> 20) - (0x3ff + 1023) + k; + expt.* = i32(hx >> 20) - (0x3ff + 1023) + k; const high_word = (hx & 0xfffff) | ((0x3ff + 1023) << 20); return @bitCast(f64, (u64(high_word) << 32) | lx); -- 2.54.0 From c38b165db4a16ba6a5c6d13537177db656fc4033 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 17 May 2018 23:21:44 -0400 Subject: [PATCH 28/47] all tests passing with postfix deref syntax --- build.zig | 59 ++++--- doc/langref.html.in | 60 +++---- src-self-hosted/arg.zig | 74 +++++---- src-self-hosted/module.zig | 18 +-- src-self-hosted/target.zig | 7 +- std/zig/ast.zig | 1 + std/zig/parse.zig | 2 +- std/zig/render.zig | 3 +- test/compare_output.zig | 4 +- test/compile_errors.zig | 30 ++-- test/standalone/brace_expansion/main.zig | 43 ++--- test/tests.zig | 190 +++++++++++------------ test/translate_c.zig | 100 ++++++------ 13 files changed, 302 insertions(+), 289 deletions(-) diff --git a/build.zig b/build.zig index b72641a2efa4d1efbcda7c88925e9c336d141dbc..a4e3dbcdfac34d5f91c3f119b42a09368ebeac6a 100644 --- a/build.zig +++ b/build.zig @@ -16,7 +16,7 @@ pub fn build(b: &Builder) !void { var docgen_exe = b.addExecutable("docgen", "doc/docgen.zig"); const rel_zig_exe = try os.path.relative(b.allocator, b.build_root, b.zig_exe); - var docgen_cmd = b.addCommand(null, b.env_map, [][]const u8 { + var docgen_cmd = b.addCommand(null, b.env_map, [][]const u8{ docgen_exe.getOutputPath(), rel_zig_exe, "doc/langref.html.in", @@ -30,7 +30,10 @@ pub fn build(b: &Builder) !void { const test_step = b.step("test", "Run all the tests"); // find the stage0 build artifacts because we're going to re-use config.h and zig_cpp library - const build_info = try b.exec([][]const u8{b.zig_exe, "BUILD_INFO"}); + const build_info = try b.exec([][]const u8{ + b.zig_exe, + "BUILD_INFO", + }); var index: usize = 0; const cmake_binary_dir = nextValue(&index, build_info); const cxx_compiler = nextValue(&index, build_info); @@ -67,7 +70,10 @@ pub fn build(b: &Builder) !void { dependOnLib(exe, llvm); if (exe.target.getOs() == builtin.Os.linux) { - const libstdcxx_path_padded = try b.exec([][]const u8{cxx_compiler, "-print-file-name=libstdc++.a"}); + const libstdcxx_path_padded = try b.exec([][]const u8{ + cxx_compiler, + "-print-file-name=libstdc++.a", + }); const libstdcxx_path = ??mem.split(libstdcxx_path_padded, "\r\n").next(); if (mem.eql(u8, libstdcxx_path, "libstdc++.a")) { warn( @@ -111,17 +117,11 @@ pub fn build(b: &Builder) !void { test_step.dependOn(docs_step); - test_step.dependOn(tests.addPkgTests(b, test_filter, - "test/behavior.zig", "behavior", "Run the behavior tests", - with_lldb)); + test_step.dependOn(tests.addPkgTests(b, test_filter, "test/behavior.zig", "behavior", "Run the behavior tests", with_lldb)); - test_step.dependOn(tests.addPkgTests(b, test_filter, - "std/index.zig", "std", "Run the standard library tests", - with_lldb)); + test_step.dependOn(tests.addPkgTests(b, test_filter, "std/index.zig", "std", "Run the standard library tests", with_lldb)); - test_step.dependOn(tests.addPkgTests(b, test_filter, - "std/special/compiler_rt/index.zig", "compiler-rt", "Run the compiler_rt tests", - with_lldb)); + test_step.dependOn(tests.addPkgTests(b, test_filter, "std/special/compiler_rt/index.zig", "compiler-rt", "Run the compiler_rt tests", with_lldb)); test_step.dependOn(tests.addCompareOutputTests(b, test_filter)); test_step.dependOn(tests.addBuildExampleTests(b, test_filter)); @@ -149,8 +149,7 @@ fn dependOnLib(lib_exe_obj: &std.build.LibExeObjStep, dep: &const LibraryDep) vo fn addCppLib(b: &Builder, lib_exe_obj: &std.build.LibExeObjStep, cmake_binary_dir: []const u8, lib_name: []const u8) void { const lib_prefix = if (lib_exe_obj.target.isWindows()) "" else "lib"; - lib_exe_obj.addObjectFile(os.path.join(b.allocator, cmake_binary_dir, "zig_cpp", - b.fmt("{}{}{}", lib_prefix, lib_name, lib_exe_obj.target.libFileExt())) catch unreachable); + lib_exe_obj.addObjectFile(os.path.join(b.allocator, cmake_binary_dir, "zig_cpp", b.fmt("{}{}{}", lib_prefix, lib_name, lib_exe_obj.target.libFileExt())) catch unreachable); } const LibraryDep = struct { @@ -161,11 +160,21 @@ const LibraryDep = struct { }; fn findLLVM(b: &Builder, llvm_config_exe: []const u8) !LibraryDep { - const libs_output = try b.exec([][]const u8{llvm_config_exe, "--libs", "--system-libs"}); - const includes_output = try b.exec([][]const u8{llvm_config_exe, "--includedir"}); - const libdir_output = try b.exec([][]const u8{llvm_config_exe, "--libdir"}); + const libs_output = try b.exec([][]const u8{ + llvm_config_exe, + "--libs", + "--system-libs", + }); + const includes_output = try b.exec([][]const u8{ + llvm_config_exe, + "--includedir", + }); + const libdir_output = try b.exec([][]const u8{ + llvm_config_exe, + "--libdir", + }); - var result = LibraryDep { + var result = LibraryDep{ .libs = ArrayList([]const u8).init(b.allocator), .system_libs = ArrayList([]const u8).init(b.allocator), .includes = ArrayList([]const u8).init(b.allocator), @@ -227,17 +236,17 @@ pub fn installCHeaders(b: &Builder, c_header_files: []const u8) void { } fn nextValue(index: &usize, build_info: []const u8) []const u8 { - const start = *index; - while (true) : (*index += 1) { - switch (build_info[*index]) { + const start = index.*; + while (true) : (index.* += 1) { + switch (build_info[index.*]) { '\n' => { - const result = build_info[start..*index]; - *index += 1; + const result = build_info[start..index.*]; + index.* += 1; return result; }, '\r' => { - const result = build_info[start..*index]; - *index += 2; + const result = build_info[start..index.*]; + index.* += 2; return result; }, else => continue, diff --git a/doc/langref.html.in b/doc/langref.html.in index cdfe7d92287a5995f64c53c8860ec2df2f710587..d047c7d9f21344591ebc265c2f86b015e3a3642d 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -1232,7 +1232,7 @@ mem.eql(u8, pattern, "ababab") -

*a
+
a.*
  • {#link|Pointers#}
  • @@ -1244,7 +1244,7 @@ mem.eql(u8, pattern, "ababab")
    const x: u32 = 1234;
     const ptr = &x;
    -*x == 1234
    +x.* == 1234
    @@ -1258,7 +1258,7 @@ const ptr = &x;
    const x: u32 = 1234;
     const ptr = &x;
    -*x == 1234
    +x.* == 1234
    @@ -1267,8 +1267,8 @@ const ptr = &x; {#header_open|Precedence#}
    x() x[] x.y
     a!b
    -!x -x -%x ~x *x &x ?x ??x
    -x{}
    +!x -x -%x ~x &x ?x ??x
    +x{} x.*
     ! * / % ** *%
     + - ++ +% -%
     << >>
    @@ -1316,7 +1316,7 @@ var some_integers: [100]i32 = undefined;
     
     test "modify an array" {
         for (some_integers) |*item, i| {
    -        *item = i32(i);
    +        item.* = i32(i);
         }
         assert(some_integers[10] == 10);
         assert(some_integers[99] == 99);
    @@ -1357,7 +1357,7 @@ comptime {
     var fancy_array = init: {
         var initial_value: [10]Point = undefined;
         for (initial_value) |*pt, i| {
    -        *pt = Point {
    +        pt.* = Point {
                 .x = i32(i),
                 .y = i32(i) * 2,
             };
    @@ -1400,7 +1400,7 @@ test "address of syntax" {
         const x_ptr = &x;
     
         // Deference a pointer:
    -    assert(*x_ptr == 1234);
    +    assert(x_ptr.* == 1234);
     
         // When you get the address of a const variable, you get a const pointer.
         assert(@typeOf(x_ptr) == &const i32);
    @@ -1409,8 +1409,8 @@ test "address of syntax" {
         var y: i32 = 5678;
         const y_ptr = &y;
         assert(@typeOf(y_ptr) == &i32);
    -    *y_ptr += 1;
    -    assert(*y_ptr == 5679);
    +    y_ptr.* += 1;
    +    assert(y_ptr.* == 5679);
     }
     
     test "pointer array access" {
    @@ -1448,9 +1448,9 @@ comptime {
         // @ptrCast.
         var x: i32 = 1;
         const ptr = &x;
    -    *ptr += 1;
    +    ptr.* += 1;
         x += 1;
    -    assert(*ptr == 3);
    +    assert(ptr.* == 3);
     }
     
     test "@ptrToInt and @intToPtr" {
    @@ -1492,7 +1492,7 @@ test "nullable pointers" {
         var x: i32 = 1;
         ptr = &x;
     
    -    assert(*??ptr == 1);
    +    assert((??ptr).* == 1);
     
         // Nullable pointers are the same size as normal pointers, because pointer
         // value 0 is used as the null value.
    @@ -1505,7 +1505,7 @@ test "pointer casting" {
         // conversions are not possible.
         const bytes align(@alignOf(u32)) = []u8{0x12, 0x12, 0x12, 0x12};
         const u32_ptr = @ptrCast(&const u32, &bytes[0]);
    -    assert(*u32_ptr == 0x12121212);
    +    assert(u32_ptr.* == 0x12121212);
     
         // Even this example is contrived - there are better ways to do the above than
         // pointer casting. For example, using a slice narrowing cast:
    @@ -1610,7 +1610,7 @@ fn foo(bytes: []u8) u32 {
           u8 can alias any memory.
           

    As an example, this code produces undefined behavior:

    -
    *@ptrCast(&u32, f32(12.34))
    +
    @ptrCast(&u32, f32(12.34)).*

    Instead, use {#link|@bitCast#}:

    @bitCast(u32, f32(12.34))

    As an added benefit, the @bitcast version works at compile-time.

    @@ -2040,7 +2040,7 @@ const Variant = union(enum) { Bool: bool, fn truthy(self: &const Variant) bool { - return switch (*self) { + return switch (self.*) { Variant.Int => |x_int| x_int != 0, Variant.Bool => |x_bool| x_bool, }; @@ -2151,7 +2151,7 @@ test "switch enum" { // A reference to the matched value can be obtained using `*` syntax. Item.C => |*item| blk: { - (*item).x += 1; + item.*.x += 1; break :blk 6; }, @@ -2374,7 +2374,7 @@ test "for reference" { // Iterate over the slice by reference by // specifying that the capture value is a pointer. for (items) |*value| { - *value += 1; + value.* += 1; } assert(items[0] == 4); @@ -2483,7 +2483,7 @@ test "if nullable" { // Access the value by reference using a pointer capture. var c: ?u32 = 3; if (c) |*value| { - *value = 2; + value.* = 2; } if (c) |value| { @@ -2524,7 +2524,7 @@ test "if error union" { // Access the value by reference using a pointer capture. var c: error!u32 = 3; if (c) |*value| { - *value = 9; + value.* = 9; } else |err| { unreachable; } @@ -3872,7 +3872,7 @@ pub fn main() void { {#header_open|@addWithOverflow#}
    @addWithOverflow(comptime T: type, a: T, b: T, result: &T) -> bool

    - Performs *result = a + b. If overflow or underflow occurs, + Performs result.* = a + b. If overflow or underflow occurs, stores the overflowed bits in result and returns true. If no overflow or underflow occurs, returns false.

    @@ -4073,9 +4073,9 @@ comptime {

    {#code_begin|syntax#} fn cmpxchgStrongButNotAtomic(comptime T: type, ptr: &T, expected_value: T, new_value: T) ?T { - const old_value = *ptr; + const old_value = ptr.*; if (old_value == expected_value) { - *ptr = new_value; + ptr.* = new_value; return null; } else { return old_value; @@ -4100,9 +4100,9 @@ fn cmpxchgStrongButNotAtomic(comptime T: type, ptr: &T, expected_value: T, new_v

    {#code_begin|syntax#} fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: &T, expected_value: T, new_value: T) ?T { - const old_value = *ptr; + const old_value = ptr.*; if (old_value == expected_value and usuallyTrueButSometimesFalse()) { - *ptr = new_value; + ptr.* = new_value; return null; } else { return old_value; @@ -4447,7 +4447,7 @@ mem.copy(u8, dest[0...byte_count], source[0...byte_count]);
    This function is a low level intrinsic with no safety mechanisms. Most code should not use this function, instead using something like this:

    -
    for (dest[0...byte_count]) |*b| *b = c;
    +
    for (dest[0...byte_count]) |*b| b.* = c;

    The optimizer is intelligent enough to turn the above snippet into a memset.

    @@ -4480,7 +4480,7 @@ mem.set(u8, dest, c);
    {#header_open|@mulWithOverflow#}
    @mulWithOverflow(comptime T: type, a: T, b: T, result: &T) -> bool

    - Performs *result = a * b. If overflow or underflow occurs, + Performs result.* = a * b. If overflow or underflow occurs, stores the overflowed bits in result and returns true. If no overflow or underflow occurs, returns false.

    @@ -4514,7 +4514,7 @@ fn targetFunction(x: i32) usize { var local_variable: i32 = 42; const ptr = &local_variable; - *ptr += 1; + ptr.* += 1; assert(local_variable == 43); return @ptrToInt(ptr); @@ -4746,7 +4746,7 @@ pub const FloatMode = enum { {#header_open|@shlWithOverflow#}
    @shlWithOverflow(comptime T: type, a: T, shift_amt: Log2T, result: &T) -> bool

    - Performs *result = a << b. If overflow or underflow occurs, + Performs result.* = a << b. If overflow or underflow occurs, stores the overflowed bits in result and returns true. If no overflow or underflow occurs, returns false.

    @@ -4790,7 +4790,7 @@ pub const FloatMode = enum { {#header_open|@subWithOverflow#}
    @subWithOverflow(comptime T: type, a: T, b: T, result: &T) -> bool

    - Performs *result = a - b. If overflow or underflow occurs, + Performs result.* = a - b. If overflow or underflow occurs, stores the overflowed bits in result and returns true. If no overflow or underflow occurs, returns false.

    diff --git a/src-self-hosted/arg.zig b/src-self-hosted/arg.zig index 707f20828715791993029d0c361d44f4af366d39..fa2166e3a53c7f42810c70790ccbab79700efc91 100644 --- a/src-self-hosted/arg.zig +++ b/src-self-hosted/arg.zig @@ -30,24 +30,22 @@ fn argInAllowedSet(maybe_set: ?[]const []const u8, arg: []const u8) bool { } // Modifies the current argument index during iteration -fn readFlagArguments(allocator: &Allocator, args: []const []const u8, required: usize, - allowed_set: ?[]const []const u8, index: &usize) !FlagArg { - +fn readFlagArguments(allocator: &Allocator, args: []const []const u8, required: usize, allowed_set: ?[]const []const u8, index: &usize) !FlagArg { switch (required) { - 0 => return FlagArg { .None = undefined }, // TODO: Required to force non-tag but value? + 0 => return FlagArg{ .None = undefined }, // TODO: Required to force non-tag but value? 1 => { - if (*index + 1 >= args.len) { + if (index.* + 1 >= args.len) { return error.MissingFlagArguments; } - *index += 1; - const arg = args[*index]; + index.* += 1; + const arg = args[index.*]; if (!argInAllowedSet(allowed_set, arg)) { return error.ArgumentNotInAllowedSet; } - return FlagArg { .Single = arg }; + return FlagArg{ .Single = arg }; }, else => |needed| { var extra = ArrayList([]const u8).init(allocator); @@ -55,12 +53,12 @@ fn readFlagArguments(allocator: &Allocator, args: []const []const u8, required: var j: usize = 0; while (j < needed) : (j += 1) { - if (*index + 1 >= args.len) { + if (index.* + 1 >= args.len) { return error.MissingFlagArguments; } - *index += 1; - const arg = args[*index]; + index.* += 1; + const arg = args[index.*]; if (!argInAllowedSet(allowed_set, arg)) { return error.ArgumentNotInAllowedSet; @@ -69,7 +67,7 @@ fn readFlagArguments(allocator: &Allocator, args: []const []const u8, required: try extra.append(arg); } - return FlagArg { .Many = extra }; + return FlagArg{ .Many = extra }; }, } } @@ -82,7 +80,7 @@ pub const Args = struct { positionals: ArrayList([]const u8), pub fn parse(allocator: &Allocator, comptime spec: []const Flag, args: []const []const u8) !Args { - var parsed = Args { + var parsed = Args{ .flags = HashMapFlags.init(allocator), .positionals = ArrayList([]const u8).init(allocator), }; @@ -116,11 +114,7 @@ pub const Args = struct { }; if (flag.mergable) { - var prev = - if (parsed.flags.get(flag_name_trimmed)) |entry| - entry.value.Many - else - ArrayList([]const u8).init(allocator); + var prev = if (parsed.flags.get(flag_name_trimmed)) |entry| entry.value.Many else ArrayList([]const u8).init(allocator); // MergeN creation disallows 0 length flag entry (doesn't make sense) switch (flag_args) { @@ -129,7 +123,7 @@ pub const Args = struct { FlagArg.Many => |inner| try prev.appendSlice(inner.toSliceConst()), } - _ = try parsed.flags.put(flag_name_trimmed, FlagArg { .Many = prev }); + _ = try parsed.flags.put(flag_name_trimmed, FlagArg{ .Many = prev }); } else { _ = try parsed.flags.put(flag_name_trimmed, flag_args); } @@ -163,7 +157,9 @@ pub const Args = struct { pub fn single(self: &Args, name: []const u8) ?[]const u8 { if (self.flags.get(name)) |entry| { switch (entry.value) { - FlagArg.Single => |inner| { return inner; }, + FlagArg.Single => |inner| { + return inner; + }, else => @panic("attempted to retrieve flag with wrong type"), } } else { @@ -175,7 +171,9 @@ pub const Args = struct { pub fn many(self: &Args, name: []const u8) ?[]const []const u8 { if (self.flags.get(name)) |entry| { switch (entry.value) { - FlagArg.Many => |inner| { return inner.toSliceConst(); }, + FlagArg.Many => |inner| { + return inner.toSliceConst(); + }, else => @panic("attempted to retrieve flag with wrong type"), } } else { @@ -207,7 +205,7 @@ pub const Flag = struct { } pub fn ArgN(comptime name: []const u8, comptime n: usize) Flag { - return Flag { + return Flag{ .name = name, .required = n, .mergable = false, @@ -220,7 +218,7 @@ pub const Flag = struct { @compileError("n must be greater than 0"); } - return Flag { + return Flag{ .name = name, .required = n, .mergable = true, @@ -229,7 +227,7 @@ pub const Flag = struct { } pub fn Option(comptime name: []const u8, comptime set: []const []const u8) Flag { - return Flag { + return Flag{ .name = name, .required = 1, .mergable = false, @@ -239,26 +237,36 @@ pub const Flag = struct { }; test "parse arguments" { - const spec1 = comptime []const Flag { + const spec1 = comptime []const Flag{ Flag.Bool("--help"), Flag.Bool("--init"), Flag.Arg1("--build-file"), - Flag.Option("--color", []const []const u8 { "on", "off", "auto" }), + Flag.Option("--color", []const []const u8{ + "on", + "off", + "auto", + }), Flag.ArgN("--pkg-begin", 2), Flag.ArgMergeN("--object", 1), Flag.ArgN("--library", 1), }; - const cliargs = []const []const u8 { + const cliargs = []const []const u8{ "build", "--help", "pos1", - "--build-file", "build.zig", - "--object", "obj1", - "--object", "obj2", - "--library", "lib1", - "--library", "lib2", - "--color", "on", + "--build-file", + "build.zig", + "--object", + "obj1", + "--object", + "obj2", + "--library", + "lib1", + "--library", + "lib2", + "--color", + "on", "pos2", }; diff --git a/src-self-hosted/module.zig b/src-self-hosted/module.zig index ccbd683bdcef47e376c26f8e17848035587e17f5..375e2e840bb7d55d952ac9d555abd533c2faa2e9 100644 --- a/src-self-hosted/module.zig +++ b/src-self-hosted/module.zig @@ -96,6 +96,7 @@ pub const Module = struct { pub const LinkLib = struct { name: []const u8, path: ?[]const u8, + /// the list of symbols we depend on from this lib symbols: ArrayList([]u8), provided_explicitly: bool, @@ -130,9 +131,7 @@ pub const Module = struct { } }; - pub fn create(allocator: &mem.Allocator, name: []const u8, root_src_path: ?[]const u8, target: &const Target, - kind: Kind, build_mode: builtin.Mode, zig_lib_dir: []const u8, cache_dir: []const u8) !&Module - { + pub fn create(allocator: &mem.Allocator, name: []const u8, root_src_path: ?[]const u8, target: &const Target, kind: Kind, build_mode: builtin.Mode, zig_lib_dir: []const u8, cache_dir: []const u8) !&Module { var name_buffer = try Buffer.init(allocator, name); errdefer name_buffer.deinit(); @@ -148,14 +147,14 @@ pub const Module = struct { const module_ptr = try allocator.create(Module); errdefer allocator.destroy(module_ptr); - *module_ptr = Module { + module_ptr.* = Module{ .allocator = allocator, .name = name_buffer, .root_src_path = root_src_path, .module = module, .context = context, .builder = builder, - .target = *target, + .target = target.*, .kind = kind, .build_mode = build_mode, .zig_lib_dir = zig_lib_dir, @@ -221,8 +220,10 @@ pub const Module = struct { pub fn build(self: &Module) !void { if (self.llvm_argv.len != 0) { - var c_compatible_args = try std.cstr.NullTerminated2DArray.fromSlices(self.allocator, - [][]const []const u8 { [][]const u8{"zig (LLVM option parsing)"}, self.llvm_argv, }); + var c_compatible_args = try std.cstr.NullTerminated2DArray.fromSlices(self.allocator, [][]const []const u8{ + [][]const u8{"zig (LLVM option parsing)"}, + self.llvm_argv, + }); defer c_compatible_args.deinit(); c.ZigLLVMParseCommandLineOptions(self.llvm_argv.len + 1, c_compatible_args.ptr); } @@ -261,7 +262,6 @@ pub const Module = struct { warn("====llvm ir:====\n"); self.dump(); - } pub fn link(self: &Module, out_file: ?[]const u8) !void { @@ -285,7 +285,7 @@ pub const Module = struct { } const link_lib = try self.allocator.create(LinkLib); - *link_lib = LinkLib { + link_lib.* = LinkLib{ .name = name, .path = null, .provided_explicitly = provided_explicitly, diff --git a/src-self-hosted/target.zig b/src-self-hosted/target.zig index 375b48f10deb77f6c2d72c5f2351fe869e0e8b2a..27a90bd0968efd5ee771d357653071b050a7bbc5 100644 --- a/src-self-hosted/target.zig +++ b/src-self-hosted/target.zig @@ -12,7 +12,7 @@ pub const Target = union(enum) { Cross: CrossTarget, pub fn oFileExt(self: &const Target) []const u8 { - const environ = switch (*self) { + const environ = switch (self.*) { Target.Native => builtin.environ, Target.Cross => |t| t.environ, }; @@ -30,7 +30,7 @@ pub const Target = union(enum) { } pub fn getOs(self: &const Target) builtin.Os { - return switch (*self) { + return switch (self.*) { Target.Native => builtin.os, Target.Cross => |t| t.os, }; @@ -38,7 +38,8 @@ pub const Target = union(enum) { pub fn isDarwin(self: &const Target) bool { return switch (self.getOs()) { - builtin.Os.ios, builtin.Os.macosx => true, + builtin.Os.ios, + builtin.Os.macosx => true, else => false, }; } diff --git a/std/zig/ast.zig b/std/zig/ast.zig index 86135fe1009e8f67358e3fd3fedb94f5b085b05b..3c1d6a5e2eec073557f002786328397cb93b2f97 100644 --- a/std/zig/ast.zig +++ b/std/zig/ast.zig @@ -1485,6 +1485,7 @@ pub const Node = struct { BitNot, BoolNot, Cancel, + PointerType, MaybeType, Negation, NegationWrap, diff --git a/std/zig/parse.zig b/std/zig/parse.zig index 154cfc0e46192b984b392c4bb0344426050b0674..f4e819e544a9cfc9a83766831002307784997758 100644 --- a/std/zig/parse.zig +++ b/std/zig/parse.zig @@ -3134,7 +3134,7 @@ fn tokenIdToPrefixOp(id: @TagType(Token.Id)) ?ast.Node.PrefixOp.Op { Token.Id.Minus => ast.Node.PrefixOp.Op{ .Negation = void{} }, Token.Id.MinusPercent => ast.Node.PrefixOp.Op{ .NegationWrap = void{} }, Token.Id.Asterisk, - Token.Id.AsteriskAsterisk => ast.Node.PrefixOp.Op{ .Deref = void{} }, + Token.Id.AsteriskAsterisk => ast.Node.PrefixOp.Op{ .PointerType = void{} }, Token.Id.Ampersand => ast.Node.PrefixOp.Op{ .AddrOf = ast.Node.PrefixOp.AddrOfInfo{ .align_expr = null, .bit_offset_start_token = null, diff --git a/std/zig/render.zig b/std/zig/render.zig index f240be87168e6e38a29c1ba0e60ec9eb400a0037..91e76e1c5f09208b448c3e9b658d2e4db4af3450 100644 --- a/std/zig/render.zig +++ b/std/zig/render.zig @@ -311,6 +311,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind ast.Node.PrefixOp.Op.Try => try stream.write("try "), ast.Node.PrefixOp.Op.UnwrapMaybe => try stream.write("??"), ast.Node.PrefixOp.Op.MaybeType => try stream.write("?"), + ast.Node.PrefixOp.Op.PointerType => try stream.write("*"), ast.Node.PrefixOp.Op.Await => try stream.write("await "), ast.Node.PrefixOp.Op.Cancel => try stream.write("cancel "), ast.Node.PrefixOp.Op.Resume => try stream.write("resume "), @@ -350,7 +351,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind try stream.write("]"); }, - ast.Node.SuffixOp.Op.SuffixOp => { + ast.Node.SuffixOp.Op.Deref => { try renderExpression(allocator, stream, tree, indent, suffix_op.lhs); try stream.write(".*"); }, diff --git a/test/compare_output.zig b/test/compare_output.zig index 9595bf8259058297f34c6d51a32cfae41c528892..b01e87d4eb819f10662ff045787393163d713a4a 100644 --- a/test/compare_output.zig +++ b/test/compare_output.zig @@ -287,9 +287,9 @@ pub fn addCases(cases: &tests.CompareOutputContext) void { \\export fn compare_fn(a: ?&const c_void, b: ?&const c_void) c_int { \\ const a_int = @ptrCast(&align(1) const i32, a ?? unreachable); \\ const b_int = @ptrCast(&align(1) const i32, b ?? unreachable); - \\ if (*a_int < *b_int) { + \\ if (a_int.* < b_int.*) { \\ return -1; - \\ } else if (*a_int > *b_int) { + \\ } else if (a_int.* > b_int.*) { \\ return 1; \\ } else { \\ return 0; diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 300f27cb6a7ea82d07907155675600a23d561b70..904ba6d9d86197b307752b28af13b1504b8cad37 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -4,7 +4,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { cases.add("invalid deref on switch target", \\comptime { \\ var tile = Tile.Empty; - \\ switch (*tile) { + \\ switch (tile.*) { \\ Tile.Empty => {}, \\ Tile.Filled => {}, \\ } @@ -14,7 +14,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\ Filled, \\}; , - ".tmp_source.zig:3:13: error: invalid deref on switch target"); + ".tmp_source.zig:3:17: error: invalid deref on switch target"); cases.add("invalid field access in comptime", \\comptime { var x = doesnt_exist.whatever; } @@ -1408,14 +1408,14 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\ Two: i32, \\}; \\fn bad_eql_2(a: &const EnumWithData, b: &const EnumWithData) bool { - \\ return *a == *b; + \\ return a.* == b.*; \\} \\ \\export fn entry1() usize { return @sizeOf(@typeOf(bad_eql_1)); } \\export fn entry2() usize { return @sizeOf(@typeOf(bad_eql_2)); } , ".tmp_source.zig:2:14: error: operator not allowed for type '[]u8'", - ".tmp_source.zig:9:15: error: operator not allowed for type 'EnumWithData'"); + ".tmp_source.zig:9:16: error: operator not allowed for type 'EnumWithData'"); cases.add("non-const switch number literal", \\export fn foo() void { @@ -1513,7 +1513,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\var bytes: [ext()]u8 = undefined; \\export fn f() void { \\ for (bytes) |*b, i| { - \\ *b = u8(i); + \\ b.* = u8(i); \\ } \\} , ".tmp_source.zig:2:13: error: unable to evaluate constant expression"); @@ -1819,7 +1819,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\} \\ \\fn bar(x: &const u3) u3 { - \\ return *x; + \\ return x.*; \\} \\ \\export fn entry() usize { return @sizeOf(@typeOf(foo)); } @@ -1903,12 +1903,12 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\var s_buffer: [10]u8 = undefined; \\pub fn pass(in: []u8) []u8 { \\ var out = &s_buffer; - \\ *out[0] = in[0]; - \\ return (*out)[0..1]; + \\ out[0].* = in[0]; + \\ return out.*[0..1]; \\} \\ \\export fn entry() usize { return @sizeOf(@typeOf(pass)); } - , ".tmp_source.zig:4:5: error: attempt to dereference non pointer type '[10]u8'"); + , ".tmp_source.zig:4:11: error: attempt to dereference non pointer type '[10]u8'"); cases.add("pass const ptr to mutable ptr fn", \\fn foo() bool { @@ -2434,7 +2434,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\} \\ \\fn bar(x: &u32) void { - \\ *x += 1; + \\ x.* += 1; \\} , ".tmp_source.zig:8:13: error: expected type '&u32', found '&align(1) u32'"); @@ -2461,7 +2461,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\export fn entry() u32 { \\ var bytes: [4]u8 = []u8{0x01, 0x02, 0x03, 0x04}; \\ const ptr = @ptrCast(&u32, &bytes[0]); - \\ return *ptr; + \\ return ptr.*; \\} , ".tmp_source.zig:3:17: error: cast increases pointer alignment", @@ -2540,14 +2540,14 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\ \\export fn entry(opaque: &Opaque) void { \\ var m2 = &2; - \\ const y: u32 = *m2; + \\ const y: u32 = m2.*; \\ \\ var a = undefined; \\ var b = 1; \\ var c = 1.0; \\ var d = this; \\ var e = null; - \\ var f = *opaque; + \\ var f = opaque.*; \\ var g = i32; \\ var h = @import("std"); \\ var i = (Foo {}).bar; @@ -3136,13 +3136,13 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\ foo(a); \\} \\fn foo(a: &const Payload) void { - \\ switch (*a) { + \\ switch (a.*) { \\ Payload.A => {}, \\ else => unreachable, \\ } \\} , - ".tmp_source.zig:11:13: error: switch on union which has no attached enum", + ".tmp_source.zig:11:14: error: switch on union which has no attached enum", ".tmp_source.zig:1:17: note: consider 'union(enum)' here"); cases.add("enum in field count range but not matching tag", diff --git a/test/standalone/brace_expansion/main.zig b/test/standalone/brace_expansion/main.zig index d4d86ae12c6010b18826e629f36d4b968b4411aa..93089ae1ffa194a81a270147b54ea4a393c433b3 100644 --- a/test/standalone/brace_expansion/main.zig +++ b/test/standalone/brace_expansion/main.zig @@ -16,7 +16,7 @@ const Token = union(enum) { var global_allocator: &mem.Allocator = undefined; -fn tokenize(input:[] const u8) !ArrayList(Token) { +fn tokenize(input: []const u8) !ArrayList(Token) { const State = enum { Start, Word, @@ -29,7 +29,8 @@ fn tokenize(input:[] const u8) !ArrayList(Token) { for (input) |b, i| { switch (state) { State.Start => switch (b) { - 'a'...'z', 'A'...'Z' => { + 'a' ... 'z', + 'A' ... 'Z' => { state = State.Word; tok_begin = i; }, @@ -39,9 +40,12 @@ fn tokenize(input:[] const u8) !ArrayList(Token) { else => return error.InvalidInput, }, State.Word => switch (b) { - 'a'...'z', 'A'...'Z' => {}, - '{', '}', ',' => { - try token_list.append(Token { .Word = input[tok_begin..i] }); + 'a' ... 'z', + 'A' ... 'Z' => {}, + '{', + '}', + ',' => { + try token_list.append(Token{ .Word = input[tok_begin..i] }); switch (b) { '{' => try token_list.append(Token.OpenBrace), '}' => try token_list.append(Token.CloseBrace), @@ -56,7 +60,7 @@ fn tokenize(input:[] const u8) !ArrayList(Token) { } switch (state) { State.Start => {}, - State.Word => try token_list.append(Token {.Word = input[tok_begin..] }), + State.Word => try token_list.append(Token{ .Word = input[tok_begin..] }), } try token_list.append(Token.Eof); return token_list; @@ -68,24 +72,24 @@ const Node = union(enum) { Combine: []Node, }; -const ParseError = error { +const ParseError = error{ InvalidInput, OutOfMemory, }; fn parse(tokens: &const ArrayList(Token), token_index: &usize) ParseError!Node { - const first_token = tokens.items[*token_index]; - *token_index += 1; + const first_token = tokens.items[token_index.*]; + token_index.* += 1; const result_node = switch (first_token) { - Token.Word => |word| Node { .Scalar = word }, + Token.Word => |word| Node{ .Scalar = word }, Token.OpenBrace => blk: { var list = ArrayList(Node).init(global_allocator); while (true) { try list.append(try parse(tokens, token_index)); - const token = tokens.items[*token_index]; - *token_index += 1; + const token = tokens.items[token_index.*]; + token_index.* += 1; switch (token) { Token.CloseBrace => break, @@ -93,17 +97,18 @@ fn parse(tokens: &const ArrayList(Token), token_index: &usize) ParseError!Node { else => return error.InvalidInput, } } - break :blk Node { .List = list }; + break :blk Node{ .List = list }; }, else => return error.InvalidInput, }; - switch (tokens.items[*token_index]) { - Token.Word, Token.OpenBrace => { + switch (tokens.items[token_index.*]) { + Token.Word, + Token.OpenBrace => { const pair = try global_allocator.alloc(Node, 2); pair[0] = result_node; pair[1] = try parse(tokens, token_index); - return Node { .Combine = pair }; + return Node{ .Combine = pair }; }, else => return result_node, } @@ -137,13 +142,11 @@ fn expandString(input: []const u8, output: &Buffer) !void { } } -const ExpandNodeError = error { - OutOfMemory, -}; +const ExpandNodeError = error{OutOfMemory}; fn expandNode(node: &const Node, output: &ArrayList(Buffer)) ExpandNodeError!void { assert(output.len == 0); - switch (*node) { + switch (node.*) { Node.Scalar => |scalar| { try output.append(try Buffer.init(global_allocator, scalar)); }, diff --git a/test/tests.zig b/test/tests.zig index 5fbb56b736faa0b19e95c80cd3daaa1bde0e8521..b59b954122afedfc697bbade85f8c2d82e76db89 100644 --- a/test/tests.zig +++ b/test/tests.zig @@ -27,18 +27,18 @@ const TestTarget = struct { environ: builtin.Environ, }; -const test_targets = []TestTarget { - TestTarget { +const test_targets = []TestTarget{ + TestTarget{ .os = builtin.Os.linux, .arch = builtin.Arch.x86_64, .environ = builtin.Environ.gnu, }, - TestTarget { + TestTarget{ .os = builtin.Os.macosx, .arch = builtin.Arch.x86_64, .environ = builtin.Environ.unknown, }, - TestTarget { + TestTarget{ .os = builtin.Os.windows, .arch = builtin.Arch.x86_64, .environ = builtin.Environ.msvc, @@ -49,7 +49,7 @@ const max_stdout_size = 1 * 1024 * 1024; // 1 MB pub fn addCompareOutputTests(b: &build.Builder, test_filter: ?[]const u8) &build.Step { const cases = b.allocator.create(CompareOutputContext) catch unreachable; - *cases = CompareOutputContext { + cases.* = CompareOutputContext{ .b = b, .step = b.step("test-compare-output", "Run the compare output tests"), .test_index = 0, @@ -63,7 +63,7 @@ pub fn addCompareOutputTests(b: &build.Builder, test_filter: ?[]const u8) &build pub fn addRuntimeSafetyTests(b: &build.Builder, test_filter: ?[]const u8) &build.Step { const cases = b.allocator.create(CompareOutputContext) catch unreachable; - *cases = CompareOutputContext { + cases.* = CompareOutputContext{ .b = b, .step = b.step("test-runtime-safety", "Run the runtime safety tests"), .test_index = 0, @@ -77,7 +77,7 @@ pub fn addRuntimeSafetyTests(b: &build.Builder, test_filter: ?[]const u8) &build pub fn addCompileErrorTests(b: &build.Builder, test_filter: ?[]const u8) &build.Step { const cases = b.allocator.create(CompileErrorContext) catch unreachable; - *cases = CompileErrorContext { + cases.* = CompileErrorContext{ .b = b, .step = b.step("test-compile-errors", "Run the compile error tests"), .test_index = 0, @@ -91,7 +91,7 @@ pub fn addCompileErrorTests(b: &build.Builder, test_filter: ?[]const u8) &build. pub fn addBuildExampleTests(b: &build.Builder, test_filter: ?[]const u8) &build.Step { const cases = b.allocator.create(BuildExamplesContext) catch unreachable; - *cases = BuildExamplesContext { + cases.* = BuildExamplesContext{ .b = b, .step = b.step("test-build-examples", "Build the examples"), .test_index = 0, @@ -105,7 +105,7 @@ pub fn addBuildExampleTests(b: &build.Builder, test_filter: ?[]const u8) &build. pub fn addAssembleAndLinkTests(b: &build.Builder, test_filter: ?[]const u8) &build.Step { const cases = b.allocator.create(CompareOutputContext) catch unreachable; - *cases = CompareOutputContext { + cases.* = CompareOutputContext{ .b = b, .step = b.step("test-asm-link", "Run the assemble and link tests"), .test_index = 0, @@ -119,7 +119,7 @@ pub fn addAssembleAndLinkTests(b: &build.Builder, test_filter: ?[]const u8) &bui pub fn addTranslateCTests(b: &build.Builder, test_filter: ?[]const u8) &build.Step { const cases = b.allocator.create(TranslateCContext) catch unreachable; - *cases = TranslateCContext { + cases.* = TranslateCContext{ .b = b, .step = b.step("test-translate-c", "Run the C transation tests"), .test_index = 0, @@ -133,7 +133,7 @@ pub fn addTranslateCTests(b: &build.Builder, test_filter: ?[]const u8) &build.St pub fn addGenHTests(b: &build.Builder, test_filter: ?[]const u8) &build.Step { const cases = b.allocator.create(GenHContext) catch unreachable; - *cases = GenHContext { + cases.* = GenHContext{ .b = b, .step = b.step("test-gen-h", "Run the C header file generation tests"), .test_index = 0, @@ -145,22 +145,26 @@ pub fn addGenHTests(b: &build.Builder, test_filter: ?[]const u8) &build.Step { return cases.step; } - -pub fn addPkgTests(b: &build.Builder, test_filter: ?[]const u8, root_src: []const u8, - name:[] const u8, desc: []const u8, with_lldb: bool) &build.Step -{ +pub fn addPkgTests(b: &build.Builder, test_filter: ?[]const u8, root_src: []const u8, name: []const u8, desc: []const u8, with_lldb: bool) &build.Step { const step = b.step(b.fmt("test-{}", name), desc); for (test_targets) |test_target| { const is_native = (test_target.os == builtin.os and test_target.arch == builtin.arch); - for ([]Mode{Mode.Debug, Mode.ReleaseSafe, Mode.ReleaseFast, Mode.ReleaseSmall}) |mode| { - for ([]bool{false, true}) |link_libc| { + for ([]Mode{ + Mode.Debug, + Mode.ReleaseSafe, + Mode.ReleaseFast, + Mode.ReleaseSmall, + }) |mode| { + for ([]bool{ + false, + true, + }) |link_libc| { if (link_libc and !is_native) { // don't assume we have a cross-compiling libc set up continue; } const these_tests = b.addTest(root_src); - these_tests.setNamePrefix(b.fmt("{}-{}-{}-{}-{} ", name, @tagName(test_target.os), - @tagName(test_target.arch), @tagName(mode), if (link_libc) "c" else "bare")); + these_tests.setNamePrefix(b.fmt("{}-{}-{}-{}-{} ", name, @tagName(test_target.os), @tagName(test_target.arch), @tagName(mode), if (link_libc) "c" else "bare")); these_tests.setFilter(test_filter); these_tests.setBuildMode(mode); if (!is_native) { @@ -171,7 +175,15 @@ pub fn addPkgTests(b: &build.Builder, test_filter: ?[]const u8, root_src: []cons } if (with_lldb) { these_tests.setExecCmd([]?[]const u8{ - "lldb", null, "-o", "run", "-o", "bt", "-o", "exit"}); + "lldb", + null, + "-o", + "run", + "-o", + "bt", + "-o", + "exit", + }); } step.dependOn(&these_tests.step); } @@ -206,7 +218,7 @@ pub const CompareOutputContext = struct { }; pub fn addSourceFile(self: &TestCase, filename: []const u8, source: []const u8) void { - self.sources.append(SourceFile { + self.sources.append(SourceFile{ .filename = filename, .source = source, }) catch unreachable; @@ -226,13 +238,10 @@ pub const CompareOutputContext = struct { test_index: usize, cli_args: []const []const u8, - pub fn create(context: &CompareOutputContext, exe_path: []const u8, - name: []const u8, expected_output: []const u8, - cli_args: []const []const u8) &RunCompareOutputStep - { + pub fn create(context: &CompareOutputContext, exe_path: []const u8, name: []const u8, expected_output: []const u8, cli_args: []const []const u8) &RunCompareOutputStep { const allocator = context.b.allocator; const ptr = allocator.create(RunCompareOutputStep) catch unreachable; - *ptr = RunCompareOutputStep { + ptr.* = RunCompareOutputStep{ .context = context, .exe_path = exe_path, .name = name, @@ -258,7 +267,7 @@ pub const CompareOutputContext = struct { args.append(arg) catch unreachable; } - warn("Test {}/{} {}...", self.test_index+1, self.context.test_index, self.name); + warn("Test {}/{} {}...", self.test_index + 1, self.context.test_index, self.name); const child = os.ChildProcess.init(args.toSliceConst(), b.allocator) catch unreachable; defer child.deinit(); @@ -295,7 +304,6 @@ pub const CompareOutputContext = struct { }, } - if (!mem.eql(u8, self.expected_output, stdout.toSliceConst())) { warn( \\ @@ -318,12 +326,10 @@ pub const CompareOutputContext = struct { name: []const u8, test_index: usize, - pub fn create(context: &CompareOutputContext, exe_path: []const u8, - name: []const u8) &RuntimeSafetyRunStep - { + pub fn create(context: &CompareOutputContext, exe_path: []const u8, name: []const u8) &RuntimeSafetyRunStep { const allocator = context.b.allocator; const ptr = allocator.create(RuntimeSafetyRunStep) catch unreachable; - *ptr = RuntimeSafetyRunStep { + ptr.* = RuntimeSafetyRunStep{ .context = context, .exe_path = exe_path, .name = name, @@ -340,7 +346,7 @@ pub const CompareOutputContext = struct { const full_exe_path = b.pathFromRoot(self.exe_path); - warn("Test {}/{} {}...", self.test_index+1, self.context.test_index, self.name); + warn("Test {}/{} {}...", self.test_index + 1, self.context.test_index, self.name); const child = os.ChildProcess.init([][]u8{full_exe_path}, b.allocator) catch unreachable; defer child.deinit(); @@ -358,19 +364,16 @@ pub const CompareOutputContext = struct { switch (term) { Term.Exited => |code| { if (code != expected_exit_code) { - warn("\nProgram expected to exit with code {} " ++ - "but exited with code {}\n", expected_exit_code, code); + warn("\nProgram expected to exit with code {} " ++ "but exited with code {}\n", expected_exit_code, code); return error.TestFailed; } }, Term.Signal => |sig| { - warn("\nProgram expected to exit with code {} " ++ - "but instead signaled {}\n", expected_exit_code, sig); + warn("\nProgram expected to exit with code {} " ++ "but instead signaled {}\n", expected_exit_code, sig); return error.TestFailed; }, else => { - warn("\nProgram expected to exit with code {}" ++ - " but exited in an unexpected way\n", expected_exit_code); + warn("\nProgram expected to exit with code {}" ++ " but exited in an unexpected way\n", expected_exit_code); return error.TestFailed; }, } @@ -379,10 +382,8 @@ pub const CompareOutputContext = struct { } }; - pub fn createExtra(self: &CompareOutputContext, name: []const u8, source: []const u8, - expected_output: []const u8, special: Special) TestCase - { - var tc = TestCase { + pub fn createExtra(self: &CompareOutputContext, name: []const u8, source: []const u8, expected_output: []const u8, special: Special) TestCase { + var tc = TestCase{ .name = name, .sources = ArrayList(TestCase.SourceFile).init(self.b.allocator), .expected_output = expected_output, @@ -395,9 +396,7 @@ pub const CompareOutputContext = struct { return tc; } - pub fn create(self: &CompareOutputContext, name: []const u8, source: []const u8, - expected_output: []const u8) TestCase - { + pub fn create(self: &CompareOutputContext, name: []const u8, source: []const u8, expected_output: []const u8) TestCase { return createExtra(self, name, source, expected_output, Special.None); } @@ -431,8 +430,7 @@ pub const CompareOutputContext = struct { Special.Asm => { const annotated_case_name = fmt.allocPrint(self.b.allocator, "assemble-and-link {}", case.name) catch unreachable; if (self.test_filter) |filter| { - if (mem.indexOf(u8, annotated_case_name, filter) == null) - return; + if (mem.indexOf(u8, annotated_case_name, filter) == null) return; } const exe = b.addExecutable("test", null); @@ -444,19 +442,21 @@ pub const CompareOutputContext = struct { exe.step.dependOn(&write_src.step); } - const run_and_cmp_output = RunCompareOutputStep.create(self, exe.getOutputPath(), annotated_case_name, - case.expected_output, case.cli_args); + const run_and_cmp_output = RunCompareOutputStep.create(self, exe.getOutputPath(), annotated_case_name, case.expected_output, case.cli_args); run_and_cmp_output.step.dependOn(&exe.step); self.step.dependOn(&run_and_cmp_output.step); }, Special.None => { - for ([]Mode{Mode.Debug, Mode.ReleaseSafe, Mode.ReleaseFast, Mode.ReleaseSmall}) |mode| { - const annotated_case_name = fmt.allocPrint(self.b.allocator, "{} {} ({})", - "compare-output", case.name, @tagName(mode)) catch unreachable; + for ([]Mode{ + Mode.Debug, + Mode.ReleaseSafe, + Mode.ReleaseFast, + Mode.ReleaseSmall, + }) |mode| { + const annotated_case_name = fmt.allocPrint(self.b.allocator, "{} {} ({})", "compare-output", case.name, @tagName(mode)) catch unreachable; if (self.test_filter) |filter| { - if (mem.indexOf(u8, annotated_case_name, filter) == null) - continue; + if (mem.indexOf(u8, annotated_case_name, filter) == null) continue; } const exe = b.addExecutable("test", root_src); @@ -471,8 +471,7 @@ pub const CompareOutputContext = struct { exe.step.dependOn(&write_src.step); } - const run_and_cmp_output = RunCompareOutputStep.create(self, exe.getOutputPath(), - annotated_case_name, case.expected_output, case.cli_args); + const run_and_cmp_output = RunCompareOutputStep.create(self, exe.getOutputPath(), annotated_case_name, case.expected_output, case.cli_args); run_and_cmp_output.step.dependOn(&exe.step); self.step.dependOn(&run_and_cmp_output.step); @@ -481,8 +480,7 @@ pub const CompareOutputContext = struct { Special.RuntimeSafety => { const annotated_case_name = fmt.allocPrint(self.b.allocator, "safety {}", case.name) catch unreachable; if (self.test_filter) |filter| { - if (mem.indexOf(u8, annotated_case_name, filter) == null) - return; + if (mem.indexOf(u8, annotated_case_name, filter) == null) return; } const exe = b.addExecutable("test", root_src); @@ -524,7 +522,7 @@ pub const CompileErrorContext = struct { }; pub fn addSourceFile(self: &TestCase, filename: []const u8, source: []const u8) void { - self.sources.append(SourceFile { + self.sources.append(SourceFile{ .filename = filename, .source = source, }) catch unreachable; @@ -543,12 +541,10 @@ pub const CompileErrorContext = struct { case: &const TestCase, build_mode: Mode, - pub fn create(context: &CompileErrorContext, name: []const u8, - case: &const TestCase, build_mode: Mode) &CompileCmpOutputStep - { + pub fn create(context: &CompileErrorContext, name: []const u8, case: &const TestCase, build_mode: Mode) &CompileCmpOutputStep { const allocator = context.b.allocator; const ptr = allocator.create(CompileCmpOutputStep) catch unreachable; - *ptr = CompileCmpOutputStep { + ptr.* = CompileCmpOutputStep{ .step = build.Step.init("CompileCmpOutput", allocator, make), .context = context, .name = name, @@ -586,7 +582,7 @@ pub const CompileErrorContext = struct { Mode.ReleaseSmall => zig_args.append("--release-small") catch unreachable, } - warn("Test {}/{} {}...", self.test_index+1, self.context.test_index, self.name); + warn("Test {}/{} {}...", self.test_index + 1, self.context.test_index, self.name); if (b.verbose) { printInvocation(zig_args.toSliceConst()); @@ -626,7 +622,6 @@ pub const CompileErrorContext = struct { }, } - const stdout = stdout_buf.toSliceConst(); const stderr = stderr_buf.toSliceConst(); @@ -666,11 +661,9 @@ pub const CompileErrorContext = struct { warn("\n"); } - pub fn create(self: &CompileErrorContext, name: []const u8, source: []const u8, - expected_lines: ...) &TestCase - { + pub fn create(self: &CompileErrorContext, name: []const u8, source: []const u8, expected_lines: ...) &TestCase { const tc = self.b.allocator.create(TestCase) catch unreachable; - *tc = TestCase { + tc.* = TestCase{ .name = name, .sources = ArrayList(TestCase.SourceFile).init(self.b.allocator), .expected_errors = ArrayList([]const u8).init(self.b.allocator), @@ -705,12 +698,13 @@ pub const CompileErrorContext = struct { pub fn addCase(self: &CompileErrorContext, case: &const TestCase) void { const b = self.b; - for ([]Mode{Mode.Debug, Mode.ReleaseFast}) |mode| { - const annotated_case_name = fmt.allocPrint(self.b.allocator, "compile-error {} ({})", - case.name, @tagName(mode)) catch unreachable; + for ([]Mode{ + Mode.Debug, + Mode.ReleaseFast, + }) |mode| { + const annotated_case_name = fmt.allocPrint(self.b.allocator, "compile-error {} ({})", case.name, @tagName(mode)) catch unreachable; if (self.test_filter) |filter| { - if (mem.indexOf(u8, annotated_case_name, filter) == null) - continue; + if (mem.indexOf(u8, annotated_case_name, filter) == null) continue; } const compile_and_cmp_errors = CompileCmpOutputStep.create(self, annotated_case_name, case, mode); @@ -744,8 +738,7 @@ pub const BuildExamplesContext = struct { const annotated_case_name = b.fmt("build {} (Debug)", build_file); if (self.test_filter) |filter| { - if (mem.indexOf(u8, annotated_case_name, filter) == null) - return; + if (mem.indexOf(u8, annotated_case_name, filter) == null) return; } var zig_args = ArrayList([]const u8).init(b.allocator); @@ -773,12 +766,15 @@ pub const BuildExamplesContext = struct { pub fn addAllArgs(self: &BuildExamplesContext, root_src: []const u8, link_libc: bool) void { const b = self.b; - for ([]Mode{Mode.Debug, Mode.ReleaseSafe, Mode.ReleaseFast, Mode.ReleaseSmall}) |mode| { - const annotated_case_name = fmt.allocPrint(self.b.allocator, "build {} ({})", - root_src, @tagName(mode)) catch unreachable; + for ([]Mode{ + Mode.Debug, + Mode.ReleaseSafe, + Mode.ReleaseFast, + Mode.ReleaseSmall, + }) |mode| { + const annotated_case_name = fmt.allocPrint(self.b.allocator, "build {} ({})", root_src, @tagName(mode)) catch unreachable; if (self.test_filter) |filter| { - if (mem.indexOf(u8, annotated_case_name, filter) == null) - continue; + if (mem.indexOf(u8, annotated_case_name, filter) == null) continue; } const exe = b.addExecutable("test", root_src); @@ -813,7 +809,7 @@ pub const TranslateCContext = struct { }; pub fn addSourceFile(self: &TestCase, filename: []const u8, source: []const u8) void { - self.sources.append(SourceFile { + self.sources.append(SourceFile{ .filename = filename, .source = source, }) catch unreachable; @@ -834,7 +830,7 @@ pub const TranslateCContext = struct { pub fn create(context: &TranslateCContext, name: []const u8, case: &const TestCase) &TranslateCCmpOutputStep { const allocator = context.b.allocator; const ptr = allocator.create(TranslateCCmpOutputStep) catch unreachable; - *ptr = TranslateCCmpOutputStep { + ptr.* = TranslateCCmpOutputStep{ .step = build.Step.init("ParseCCmpOutput", allocator, make), .context = context, .name = name, @@ -857,7 +853,7 @@ pub const TranslateCContext = struct { zig_args.append("translate-c") catch unreachable; zig_args.append(b.pathFromRoot(root_src)) catch unreachable; - warn("Test {}/{} {}...", self.test_index+1, self.context.test_index, self.name); + warn("Test {}/{} {}...", self.test_index + 1, self.context.test_index, self.name); if (b.verbose) { printInvocation(zig_args.toSliceConst()); @@ -939,11 +935,9 @@ pub const TranslateCContext = struct { warn("\n"); } - pub fn create(self: &TranslateCContext, allow_warnings: bool, filename: []const u8, name: []const u8, - source: []const u8, expected_lines: ...) &TestCase - { + pub fn create(self: &TranslateCContext, allow_warnings: bool, filename: []const u8, name: []const u8, source: []const u8, expected_lines: ...) &TestCase { const tc = self.b.allocator.create(TestCase) catch unreachable; - *tc = TestCase { + tc.* = TestCase{ .name = name, .sources = ArrayList(TestCase.SourceFile).init(self.b.allocator), .expected_lines = ArrayList([]const u8).init(self.b.allocator), @@ -977,8 +971,7 @@ pub const TranslateCContext = struct { const annotated_case_name = fmt.allocPrint(self.b.allocator, "translate-c {}", case.name) catch unreachable; if (self.test_filter) |filter| { - if (mem.indexOf(u8, annotated_case_name, filter) == null) - return; + if (mem.indexOf(u8, annotated_case_name, filter) == null) return; } const translate_c_and_cmp = TranslateCCmpOutputStep.create(self, annotated_case_name, case); @@ -1009,7 +1002,7 @@ pub const GenHContext = struct { }; pub fn addSourceFile(self: &TestCase, filename: []const u8, source: []const u8) void { - self.sources.append(SourceFile { + self.sources.append(SourceFile{ .filename = filename, .source = source, }) catch unreachable; @@ -1031,7 +1024,7 @@ pub const GenHContext = struct { pub fn create(context: &GenHContext, h_path: []const u8, name: []const u8, case: &const TestCase) &GenHCmpOutputStep { const allocator = context.b.allocator; const ptr = allocator.create(GenHCmpOutputStep) catch unreachable; - *ptr = GenHCmpOutputStep { + ptr.* = GenHCmpOutputStep{ .step = build.Step.init("ParseCCmpOutput", allocator, make), .context = context, .h_path = h_path, @@ -1047,7 +1040,7 @@ pub const GenHContext = struct { const self = @fieldParentPtr(GenHCmpOutputStep, "step", step); const b = self.context.b; - warn("Test {}/{} {}...", self.test_index+1, self.context.test_index, self.name); + warn("Test {}/{} {}...", self.test_index + 1, self.context.test_index, self.name); const full_h_path = b.pathFromRoot(self.h_path); const actual_h = try io.readFileAlloc(b.allocator, full_h_path); @@ -1076,11 +1069,9 @@ pub const GenHContext = struct { warn("\n"); } - pub fn create(self: &GenHContext, filename: []const u8, name: []const u8, - source: []const u8, expected_lines: ...) &TestCase - { + pub fn create(self: &GenHContext, filename: []const u8, name: []const u8, source: []const u8, expected_lines: ...) &TestCase { const tc = self.b.allocator.create(TestCase) catch unreachable; - *tc = TestCase { + tc.* = TestCase{ .name = name, .sources = ArrayList(TestCase.SourceFile).init(self.b.allocator), .expected_lines = ArrayList([]const u8).init(self.b.allocator), @@ -1105,8 +1096,7 @@ pub const GenHContext = struct { const mode = builtin.Mode.Debug; const annotated_case_name = fmt.allocPrint(self.b.allocator, "gen-h {} ({})", case.name, @tagName(mode)) catch unreachable; if (self.test_filter) |filter| { - if (mem.indexOf(u8, annotated_case_name, filter) == null) - return; + if (mem.indexOf(u8, annotated_case_name, filter) == null) return; } const obj = b.addObject("test", root_src); diff --git a/test/translate_c.zig b/test/translate_c.zig index 2cd59f6f75fc29277c6a5a3b14ba8945f3a6b546..2054cfa246f88a6bc64f479b9ed3f6bf486055c8 100644 --- a/test/translate_c.zig +++ b/test/translate_c.zig @@ -720,43 +720,43 @@ pub fn addCases(cases: &tests.TranslateCContext) void { \\ var a: c_int = 0; \\ a += x: { \\ const _ref = &a; - \\ (*_ref) = ((*_ref) + 1); - \\ break :x *_ref; + \\ _ref.* = (_ref.* + 1); + \\ break :x _ref.*; \\ }; \\ a -= x: { \\ const _ref = &a; - \\ (*_ref) = ((*_ref) - 1); - \\ break :x *_ref; + \\ _ref.* = (_ref.* - 1); + \\ break :x _ref.*; \\ }; \\ a *= x: { \\ const _ref = &a; - \\ (*_ref) = ((*_ref) * 1); - \\ break :x *_ref; + \\ _ref.* = (_ref.* * 1); + \\ break :x _ref.*; \\ }; \\ a &= x: { \\ const _ref = &a; - \\ (*_ref) = ((*_ref) & 1); - \\ break :x *_ref; + \\ _ref.* = (_ref.* & 1); + \\ break :x _ref.*; \\ }; \\ a |= x: { \\ const _ref = &a; - \\ (*_ref) = ((*_ref) | 1); - \\ break :x *_ref; + \\ _ref.* = (_ref.* | 1); + \\ break :x _ref.*; \\ }; \\ a ^= x: { \\ const _ref = &a; - \\ (*_ref) = ((*_ref) ^ 1); - \\ break :x *_ref; + \\ _ref.* = (_ref.* ^ 1); + \\ break :x _ref.*; \\ }; \\ a >>= @import("std").math.Log2Int(c_int)(x: { \\ const _ref = &a; - \\ (*_ref) = ((*_ref) >> @import("std").math.Log2Int(c_int)(1)); - \\ break :x *_ref; + \\ _ref.* = (_ref.* >> @import("std").math.Log2Int(c_int)(1)); + \\ break :x _ref.*; \\ }); \\ a <<= @import("std").math.Log2Int(c_int)(x: { \\ const _ref = &a; - \\ (*_ref) = ((*_ref) << @import("std").math.Log2Int(c_int)(1)); - \\ break :x *_ref; + \\ _ref.* = (_ref.* << @import("std").math.Log2Int(c_int)(1)); + \\ break :x _ref.*; \\ }); \\} ); @@ -778,43 +778,43 @@ pub fn addCases(cases: &tests.TranslateCContext) void { \\ var a: c_uint = c_uint(0); \\ a +%= x: { \\ const _ref = &a; - \\ (*_ref) = ((*_ref) +% c_uint(1)); - \\ break :x *_ref; + \\ _ref.* = (_ref.* +% c_uint(1)); + \\ break :x _ref.*; \\ }; \\ a -%= x: { \\ const _ref = &a; - \\ (*_ref) = ((*_ref) -% c_uint(1)); - \\ break :x *_ref; + \\ _ref.* = (_ref.* -% c_uint(1)); + \\ break :x _ref.*; \\ }; \\ a *%= x: { \\ const _ref = &a; - \\ (*_ref) = ((*_ref) *% c_uint(1)); - \\ break :x *_ref; + \\ _ref.* = (_ref.* *% c_uint(1)); + \\ break :x _ref.*; \\ }; \\ a &= x: { \\ const _ref = &a; - \\ (*_ref) = ((*_ref) & c_uint(1)); - \\ break :x *_ref; + \\ _ref.* = (_ref.* & c_uint(1)); + \\ break :x _ref.*; \\ }; \\ a |= x: { \\ const _ref = &a; - \\ (*_ref) = ((*_ref) | c_uint(1)); - \\ break :x *_ref; + \\ _ref.* = (_ref.* | c_uint(1)); + \\ break :x _ref.*; \\ }; \\ a ^= x: { \\ const _ref = &a; - \\ (*_ref) = ((*_ref) ^ c_uint(1)); - \\ break :x *_ref; + \\ _ref.* = (_ref.* ^ c_uint(1)); + \\ break :x _ref.*; \\ }; \\ a >>= @import("std").math.Log2Int(c_uint)(x: { \\ const _ref = &a; - \\ (*_ref) = ((*_ref) >> @import("std").math.Log2Int(c_uint)(1)); - \\ break :x *_ref; + \\ _ref.* = (_ref.* >> @import("std").math.Log2Int(c_uint)(1)); + \\ break :x _ref.*; \\ }); \\ a <<= @import("std").math.Log2Int(c_uint)(x: { \\ const _ref = &a; - \\ (*_ref) = ((*_ref) << @import("std").math.Log2Int(c_uint)(1)); - \\ break :x *_ref; + \\ _ref.* = (_ref.* << @import("std").math.Log2Int(c_uint)(1)); + \\ break :x _ref.*; \\ }); \\} ); @@ -853,26 +853,26 @@ pub fn addCases(cases: &tests.TranslateCContext) void { \\ u -%= 1; \\ i = x: { \\ const _ref = &i; - \\ const _tmp = *_ref; - \\ (*_ref) += 1; + \\ const _tmp = _ref.*; + \\ _ref.* += 1; \\ break :x _tmp; \\ }; \\ i = x: { \\ const _ref = &i; - \\ const _tmp = *_ref; - \\ (*_ref) -= 1; + \\ const _tmp = _ref.*; + \\ _ref.* -= 1; \\ break :x _tmp; \\ }; \\ u = x: { \\ const _ref = &u; - \\ const _tmp = *_ref; - \\ (*_ref) +%= 1; + \\ const _tmp = _ref.*; + \\ _ref.* +%= 1; \\ break :x _tmp; \\ }; \\ u = x: { \\ const _ref = &u; - \\ const _tmp = *_ref; - \\ (*_ref) -%= 1; + \\ const _tmp = _ref.*; + \\ _ref.* -%= 1; \\ break :x _tmp; \\ }; \\} @@ -901,23 +901,23 @@ pub fn addCases(cases: &tests.TranslateCContext) void { \\ u -%= 1; \\ i = x: { \\ const _ref = &i; - \\ (*_ref) += 1; - \\ break :x *_ref; + \\ _ref.* += 1; + \\ break :x _ref.*; \\ }; \\ i = x: { \\ const _ref = &i; - \\ (*_ref) -= 1; - \\ break :x *_ref; + \\ _ref.* -= 1; + \\ break :x _ref.*; \\ }; \\ u = x: { \\ const _ref = &u; - \\ (*_ref) +%= 1; - \\ break :x *_ref; + \\ _ref.* +%= 1; + \\ break :x _ref.*; \\ }; \\ u = x: { \\ const _ref = &u; - \\ (*_ref) -%= 1; - \\ break :x *_ref; + \\ _ref.* -%= 1; + \\ break :x _ref.*; \\ }; \\} ); @@ -985,7 +985,7 @@ pub fn addCases(cases: &tests.TranslateCContext) void { \\} , \\pub export fn foo(x: ?&c_int) void { - \\ (*??x) = 1; + \\ (??x).* = 1; \\} ); @@ -1013,7 +1013,7 @@ pub fn addCases(cases: &tests.TranslateCContext) void { \\pub fn foo() c_int { \\ var x: c_int = 1234; \\ var ptr: ?&c_int = &x; - \\ return *??ptr; + \\ return (??ptr).*; \\} ); -- 2.54.0 From bfbe26734d4167977fff0d675ff55c68d75dd3be Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 20 May 2018 14:50:27 -0400 Subject: [PATCH 29/47] zig fmt: add pointer deref syntax --- std/zig/parse.zig | 11 +++++++++++ std/zig/parser_test.zig | 7 +++++++ 2 files changed, 18 insertions(+) diff --git a/std/zig/parse.zig b/std/zig/parse.zig index f4e819e544a9cfc9a83766831002307784997758..865ece6f5d5c8838f8c8f24b89e5638df0888be0 100644 --- a/std/zig/parse.zig +++ b/std/zig/parse.zig @@ -2195,6 +2195,17 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { continue; }, Token.Id.Period => { + if (eatToken(&tok_it, &tree, Token.Id.Asterisk)) |asterisk_token| { + const node = try arena.construct(ast.Node.SuffixOp{ + .base = ast.Node{ .id = ast.Node.Id.SuffixOp }, + .lhs = lhs, + .op = ast.Node.SuffixOp.Op.Deref, + .rtoken = asterisk_token, + }); + opt_ctx.store(&node.base); + stack.append(State{ .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable; + continue; + } const node = try arena.construct(ast.Node.InfixOp{ .base = ast.Node{ .id = ast.Node.Id.InfixOp }, .lhs = lhs, diff --git a/std/zig/parser_test.zig b/std/zig/parser_test.zig index 094c4d51f721d1e677b5a62058a3ae30649e308c..63d56167e83195c1e9674af9b664ab31d0485d4a 100644 --- a/std/zig/parser_test.zig +++ b/std/zig/parser_test.zig @@ -1,3 +1,10 @@ +test "zig fmt: ptr deref operator" { + try testCanonical( + \\const a = b.*; + \\ + ); +} + test "zig fmt: comment after if before another if" { try testCanonical( \\test "aoeu" { -- 2.54.0 From 698c52e7961a78e68be39f4a6216f5c3d55f4f3f Mon Sep 17 00:00:00 2001 From: Marc Tiehuis Date: Tue, 22 May 2018 15:32:17 +1200 Subject: [PATCH 30/47] Make StreamingJsonParser public --- std/json.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/std/json.zig b/std/json.zig index 2ea9083e2f96749e9ca19cd1ddb7849f6b63eca1..b73397cd26621f6136e6aee931dd260977acad95 100644 --- a/std/json.zig +++ b/std/json.zig @@ -86,7 +86,7 @@ pub const Token = struct { // parsing state requires ~40-50 bytes of stack space. // // Conforms strictly to RFC8529. -const StreamingJsonParser = struct { +pub const StreamingJsonParser = struct { // Current state state: State, // How many bytes we have counted for the current token -- 2.54.0 From 4f4afe186d854fb81aca7db4862c366271f24d06 Mon Sep 17 00:00:00 2001 From: Marc Tiehuis Date: Tue, 22 May 2018 15:34:17 +1200 Subject: [PATCH 31/47] Make JsonParser public --- std/json.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/std/json.zig b/std/json.zig index b73397cd26621f6136e6aee931dd260977acad95..e96989940366c968bde34181d921e4693149cd34 100644 --- a/std/json.zig +++ b/std/json.zig @@ -1053,7 +1053,7 @@ pub const Value = union(enum) { }; // A non-stream JSON parser which constructs a tree of Value's. -const JsonParser = struct { +pub const JsonParser = struct { allocator: &Allocator, state: State, copy_strings: bool, -- 2.54.0 From b132a17a749c27040c7fed43b268c2f0d9a401ce Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 20 May 2018 21:59:20 -0400 Subject: [PATCH 32/47] std.zig.parse ignores comments std.zig.render handles comments by looking at nearby tokens --- README.md | 3 + std/zig/ast.zig | 81 ++- std/zig/parse.zig | 255 ++++----- std/zig/parser_test.zig | 89 ++- std/zig/render.zig | 1166 ++++++++++++++++++++++----------------- 5 files changed, 896 insertions(+), 698 deletions(-) diff --git a/README.md b/README.md index 552b784a501f3fe6771a522fd75b81db82ba8bbf..cf4d8179c7528edd04987a22faceb9ce02cf488e 100644 --- a/README.md +++ b/README.md @@ -182,6 +182,9 @@ binary. This is the actual compiler binary that we will install to the system. +*Note: Stage 2 compiler is not yet able to build Stage 3. Building Stage 3 is +not yet supported.* + #### Debug / Development Build ``` diff --git a/std/zig/ast.zig b/std/zig/ast.zig index 3c1d6a5e2eec073557f002786328397cb93b2f97..c1552b022070ff14d8f27cd24f12ac3580499414 100644 --- a/std/zig/ast.zig +++ b/std/zig/ast.zig @@ -71,6 +71,24 @@ pub const Tree = struct { pub fn dump(self: &Tree) void { self.root_node.base.dump(0); } + + /// Skips over comments + pub fn prevToken(self: &Tree, token_index: TokenIndex) TokenIndex { + var index = token_index - 1; + while (self.tokens.at(index).id == Token.Id.LineComment) { + index -= 1; + } + return index; + } + + /// Skips over comments + pub fn nextToken(self: &Tree, token_index: TokenIndex) TokenIndex { + var index = token_index + 1; + while (self.tokens.at(index).id == Token.Id.LineComment) { + index += 1; + } + return index; + } }; pub const Error = union(enum) { @@ -272,7 +290,6 @@ pub const Node = struct { Block, // Misc - LineComment, DocComment, SwitchCase, SwitchElse, @@ -359,7 +376,6 @@ pub const Node = struct { Id.SwitchElse, Id.FieldInitializer, Id.DocComment, - Id.LineComment, Id.TestDecl => return false, Id.While => { const while_node = @fieldParentPtr(While, "base", n); @@ -506,6 +522,7 @@ pub const Node = struct { base: Node, doc_comments: ?&DocComment, visib_token: ?TokenIndex, + use_token: TokenIndex, expr: &Node, semicolon_token: TokenIndex, @@ -520,7 +537,7 @@ pub const Node = struct { pub fn firstToken(self: &Use) TokenIndex { if (self.visib_token) |visib_token| return visib_token; - return self.expr.firstToken(); + return self.use_token; } pub fn lastToken(self: &Use) TokenIndex { @@ -556,27 +573,15 @@ pub const Node = struct { pub const ContainerDecl = struct { base: Node, - ltoken: TokenIndex, - layout: Layout, - kind: Kind, + layout_token: ?TokenIndex, + kind_token: TokenIndex, init_arg_expr: InitArg, fields_and_decls: DeclList, + lbrace_token: TokenIndex, rbrace_token: TokenIndex, pub const DeclList = Root.DeclList; - const Layout = enum { - Auto, - Extern, - Packed, - }; - - const Kind = enum { - Struct, - Enum, - Union, - }; - const InitArg = union(enum) { None, Enum: ?&Node, @@ -602,7 +607,10 @@ pub const Node = struct { } pub fn firstToken(self: &ContainerDecl) TokenIndex { - return self.ltoken; + if (self.layout_token) |layout_token| { + return layout_token; + } + return self.kind_token; } pub fn lastToken(self: &ContainerDecl) TokenIndex { @@ -1113,7 +1121,7 @@ pub const Node = struct { switch_token: TokenIndex, expr: &Node, - /// these can be SwitchCase nodes or LineComment nodes + /// these must be SwitchCase nodes cases: CaseList, rbrace: TokenIndex, @@ -1143,6 +1151,7 @@ pub const Node = struct { pub const SwitchCase = struct { base: Node, items: ItemList, + arrow_token: TokenIndex, payload: ?&Node, expr: &Node, @@ -1963,9 +1972,11 @@ pub const Node = struct { pub const AsmOutput = struct { base: Node, + lbracket: TokenIndex, symbolic_name: &Node, constraint: &Node, kind: Kind, + rparen: TokenIndex, const Kind = union(enum) { Variable: &Identifier, @@ -1996,22 +2007,21 @@ pub const Node = struct { } pub fn firstToken(self: &AsmOutput) TokenIndex { - return self.symbolic_name.firstToken(); + return self.lbracket; } pub fn lastToken(self: &AsmOutput) TokenIndex { - return switch (self.kind) { - Kind.Variable => |variable_name| variable_name.lastToken(), - Kind.Return => |return_type| return_type.lastToken(), - }; + return self.rparen; } }; pub const AsmInput = struct { base: Node, + lbracket: TokenIndex, symbolic_name: &Node, constraint: &Node, expr: &Node, + rparen: TokenIndex, pub fn iterate(self: &AsmInput, index: usize) ?&Node { var i = index; @@ -2029,11 +2039,11 @@ pub const Node = struct { } pub fn firstToken(self: &AsmInput) TokenIndex { - return self.symbolic_name.firstToken(); + return self.lbracket; } pub fn lastToken(self: &AsmInput) TokenIndex { - return self.expr.lastToken(); + return self.rparen; } }; @@ -2126,23 +2136,6 @@ pub const Node = struct { } }; - pub const LineComment = struct { - base: Node, - token: TokenIndex, - - pub fn iterate(self: &LineComment, index: usize) ?&Node { - return null; - } - - pub fn firstToken(self: &LineComment) TokenIndex { - return self.token; - } - - pub fn lastToken(self: &LineComment) TokenIndex { - return self.token; - } - }; - pub const DocComment = struct { base: Node, lines: LineList, diff --git a/std/zig/parse.zig b/std/zig/parse.zig index 865ece6f5d5c8838f8c8f24b89e5638df0888be0..826ea2c3e1ab6cba30647feefbbb89a87bece1de 100644 --- a/std/zig/parse.zig +++ b/std/zig/parse.zig @@ -49,10 +49,6 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { switch (state) { State.TopLevel => { - while (try eatLineComment(arena, &tok_it, &tree)) |line_comment| { - try root_node.decls.push(&line_comment.base); - } - const comments = try eatDocComments(arena, &tok_it, &tree); const token = nextToken(&tok_it, &tree); @@ -80,7 +76,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { try stack.append(State{ .Block = block }); try stack.append(State{ .ExpectTokenSave = ExpectTokenSave{ .id = Token.Id.LBrace, - .ptr = &block.rbrace, + .ptr = &block.lbrace, } }); try stack.append(State{ .StringLiteral = OptionalCtx{ .Required = &test_node.name } }); continue; @@ -121,12 +117,12 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { try stack.append(State{ .Block = block }); try stack.append(State{ .ExpectTokenSave = ExpectTokenSave{ .id = Token.Id.LBrace, - .ptr = &block.rbrace, + .ptr = &block.lbrace, } }); continue; }, else => { - putBackToken(&tok_it, &tree); + prevToken(&tok_it, &tree); stack.append(State.TopLevel) catch unreachable; try stack.append(State{ .TopLevelExtern = TopLevelDeclCtx{ .decls = &root_node.decls, @@ -172,7 +168,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { continue; }, else => { - putBackToken(&tok_it, &tree); + prevToken(&tok_it, &tree); stack.append(State{ .TopLevelDecl = ctx }) catch unreachable; continue; }, @@ -184,7 +180,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { const lib_name_token_index = lib_name_token.index; const lib_name_token_ptr = lib_name_token.ptr; break :blk (try parseStringLiteral(arena, &tok_it, lib_name_token_ptr, lib_name_token_index, &tree)) ?? { - putBackToken(&tok_it, &tree); + prevToken(&tok_it, &tree); break :blk null; }; }; @@ -211,6 +207,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { const node = try arena.construct(ast.Node.Use{ .base = ast.Node{ .id = ast.Node.Id.Use }, + .use_token = token_index, .visib_token = ctx.visib_token, .expr = undefined, .semicolon_token = undefined, @@ -310,7 +307,6 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { }, State.TopLevelExternOrField => |ctx| { if (eatToken(&tok_it, &tree, Token.Id.Identifier)) |identifier| { - std.debug.assert(ctx.container_decl.kind == ast.Node.ContainerDecl.Kind.Struct); const node = try arena.construct(ast.Node.StructField{ .base = ast.Node{ .id = ast.Node.Id.StructField }, .doc_comments = ctx.comments, @@ -343,7 +339,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { const eq_tok_index = eq_tok.index; const eq_tok_ptr = eq_tok.ptr; if (eq_tok_ptr.id != Token.Id.Equal) { - putBackToken(&tok_it, &tree); + prevToken(&tok_it, &tree); continue; } stack.append(State{ .Expression = ctx }) catch unreachable; @@ -356,12 +352,11 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { const token_ptr = token.ptr; const node = try arena.construct(ast.Node.ContainerDecl{ .base = ast.Node{ .id = ast.Node.Id.ContainerDecl }, - .ltoken = ctx.ltoken, - .layout = ctx.layout, - .kind = switch (token_ptr.id) { - Token.Id.Keyword_struct => ast.Node.ContainerDecl.Kind.Struct, - Token.Id.Keyword_union => ast.Node.ContainerDecl.Kind.Union, - Token.Id.Keyword_enum => ast.Node.ContainerDecl.Kind.Enum, + .layout_token = ctx.layout_token, + .kind_token = switch (token_ptr.id) { + Token.Id.Keyword_struct, + Token.Id.Keyword_union, + Token.Id.Keyword_enum => token_index, else => { ((try tree.errors.addOne())).* = Error{ .ExpectedAggregateKw = Error.ExpectedAggregateKw{ .token = token_index } }; return tree; @@ -369,12 +364,16 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { }, .init_arg_expr = ast.Node.ContainerDecl.InitArg.None, .fields_and_decls = ast.Node.ContainerDecl.DeclList.init(arena), + .lbrace_token = undefined, .rbrace_token = undefined, }); ctx.opt_ctx.store(&node.base); stack.append(State{ .ContainerDecl = node }) catch unreachable; - try stack.append(State{ .ExpectToken = Token.Id.LBrace }); + try stack.append(State{ .ExpectTokenSave = ExpectTokenSave{ + .id = Token.Id.LBrace, + .ptr = &node.lbrace_token, + } }); try stack.append(State{ .ContainerInitArgStart = node }); continue; }, @@ -403,11 +402,11 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { try stack.append(State{ .ExpectToken = Token.Id.RParen }); try stack.append(State{ .Expression = OptionalCtx{ .RequiredNull = &container_decl.init_arg_expr.Enum } }); } else { - putBackToken(&tok_it, &tree); + prevToken(&tok_it, &tree); } }, else => { - putBackToken(&tok_it, &tree); + prevToken(&tok_it, &tree); container_decl.init_arg_expr = ast.Node.ContainerDecl.InitArg{ .Type = undefined }; stack.append(State{ .Expression = OptionalCtx{ .Required = &container_decl.init_arg_expr.Type } }) catch unreachable; }, @@ -416,18 +415,14 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { }, State.ContainerDecl => |container_decl| { - while (try eatLineComment(arena, &tok_it, &tree)) |line_comment| { - try container_decl.fields_and_decls.push(&line_comment.base); - } - const comments = try eatDocComments(arena, &tok_it, &tree); const token = nextToken(&tok_it, &tree); const token_index = token.index; const token_ptr = token.ptr; switch (token_ptr.id) { Token.Id.Identifier => { - switch (container_decl.kind) { - ast.Node.ContainerDecl.Kind.Struct => { + switch (tree.tokens.at(container_decl.kind_token).id) { + Token.Id.Keyword_struct => { const node = try arena.construct(ast.Node.StructField{ .base = ast.Node{ .id = ast.Node.Id.StructField }, .doc_comments = comments, @@ -443,7 +438,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { try stack.append(State{ .ExpectToken = Token.Id.Colon }); continue; }, - ast.Node.ContainerDecl.Kind.Union => { + Token.Id.Keyword_union => { const node = try arena.construct(ast.Node.UnionTag{ .base = ast.Node{ .id = ast.Node.Id.UnionTag }, .name_token = token_index, @@ -459,7 +454,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { try stack.append(State{ .IfToken = Token.Id.Colon }); continue; }, - ast.Node.ContainerDecl.Kind.Enum => { + Token.Id.Keyword_enum => { const node = try arena.construct(ast.Node.EnumTag{ .base = ast.Node{ .id = ast.Node.Id.EnumTag }, .name_token = token_index, @@ -473,11 +468,12 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { try stack.append(State{ .IfToken = Token.Id.Equal }); continue; }, + else => unreachable, } }, Token.Id.Keyword_pub => { - switch (container_decl.kind) { - ast.Node.ContainerDecl.Kind.Struct => { + switch (tree.tokens.at(container_decl.kind_token).id) { + Token.Id.Keyword_struct => { try stack.append(State{ .TopLevelExternOrField = TopLevelExternOrFieldCtx{ .visib_token = token_index, .container_decl = container_decl, @@ -518,7 +514,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { continue; }, else => { - putBackToken(&tok_it, &tree); + prevToken(&tok_it, &tree); stack.append(State{ .ContainerDecl = container_decl }) catch unreachable; try stack.append(State{ .TopLevelExtern = TopLevelDeclCtx{ .decls = &container_decl.fields_and_decls, @@ -573,7 +569,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { continue; } - putBackToken(&tok_it, &tree); + prevToken(&tok_it, &tree); continue; }, State.VarDeclEq => |var_decl| { @@ -616,7 +612,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { if (loc.line == 0) { try pushDocComment(arena, doc_comment_token, &var_decl.doc_comments); } else { - putBackToken(&tok_it, &tree); + prevToken(&tok_it, &tree); } } }, @@ -688,7 +684,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { } } - putBackToken(&tok_it, &tree); + prevToken(&tok_it, &tree); fn_proto.return_type = ast.Node.FnProto.ReturnType{ .Explicit = undefined }; stack.append(State{ .TypeExprBegin = OptionalCtx{ .Required = &fn_proto.return_type.Explicit } }) catch unreachable; continue; @@ -733,7 +729,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { if (eatToken(&tok_it, &tree, Token.Id.Colon)) |_| { param_decl.name_token = ident_token; } else { - putBackToken(&tok_it, &tree); + prevToken(&tok_it, &tree); } } continue; @@ -838,7 +834,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { return tree; } - putBackToken(&tok_it, &tree); + prevToken(&tok_it, &tree); continue; }, } @@ -872,7 +868,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { return tree; } - putBackToken(&tok_it, &tree); + prevToken(&tok_it, &tree); continue; }, } @@ -927,11 +923,6 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { continue; }, State.Else => |dest| { - const old_index = tok_it.index; - var need_index_restore = false; - while (try eatLineComment(arena, &tok_it, &tree)) |_| { - need_index_restore = true; - } if (eatToken(&tok_it, &tree, Token.Id.Keyword_else)) |else_token| { const node = try arena.construct(ast.Node.Else{ .base = ast.Node{ .id = ast.Node.Id.Else }, @@ -945,9 +936,6 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { try stack.append(State{ .Payload = OptionalCtx{ .Optional = &node.payload } }); continue; } else { - if (need_index_restore) { - tok_it.set(old_index); - } continue; } }, @@ -962,16 +950,9 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { continue; }, else => { - putBackToken(&tok_it, &tree); + prevToken(&tok_it, &tree); stack.append(State{ .Block = block }) catch unreachable; - var any_comments = false; - while (try eatLineComment(arena, &tok_it, &tree)) |line_comment| { - try block.statements.push(&line_comment.base); - any_comments = true; - } - if (any_comments) continue; - try stack.append(State{ .Statement = block }); continue; }, @@ -1035,7 +1016,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { continue; }, else => { - putBackToken(&tok_it, &tree); + prevToken(&tok_it, &tree); const statement = try block.statements.addOne(); try stack.append(State{ .Semicolon = statement }); try stack.append(State{ .AssignmentExpressionBegin = OptionalCtx{ .Required = statement } }); @@ -1062,8 +1043,8 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { continue; }, else => { - putBackToken(&tok_it, &tree); - putBackToken(&tok_it, &tree); + prevToken(&tok_it, &tree); + prevToken(&tok_it, &tree); const statement = try ctx.block.statements.addOne(); try stack.append(State{ .Semicolon = statement }); try stack.append(State{ .Expression = OptionalCtx{ .Required = statement } }); @@ -1085,21 +1066,26 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { const lbracket_index = lbracket.index; const lbracket_ptr = lbracket.ptr; if (lbracket_ptr.id != Token.Id.LBracket) { - putBackToken(&tok_it, &tree); + prevToken(&tok_it, &tree); continue; } const node = try arena.construct(ast.Node.AsmOutput{ .base = ast.Node{ .id = ast.Node.Id.AsmOutput }, + .lbracket = lbracket_index, .symbolic_name = undefined, .constraint = undefined, .kind = undefined, + .rparen = undefined, }); try items.push(node); stack.append(State{ .AsmOutputItems = items }) catch unreachable; try stack.append(State{ .IfToken = Token.Id.Comma }); - try stack.append(State{ .ExpectToken = Token.Id.RParen }); + try stack.append(State{ .ExpectTokenSave = ExpectTokenSave{ + .id = Token.Id.RParen, + .ptr = &node.rparen, + } }); try stack.append(State{ .AsmOutputReturnOrType = node }); try stack.append(State{ .ExpectToken = Token.Id.LParen }); try stack.append(State{ .StringLiteral = OptionalCtx{ .Required = &node.constraint } }); @@ -1132,21 +1118,26 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { const lbracket_index = lbracket.index; const lbracket_ptr = lbracket.ptr; if (lbracket_ptr.id != Token.Id.LBracket) { - putBackToken(&tok_it, &tree); + prevToken(&tok_it, &tree); continue; } const node = try arena.construct(ast.Node.AsmInput{ .base = ast.Node{ .id = ast.Node.Id.AsmInput }, + .lbracket = lbracket_index, .symbolic_name = undefined, .constraint = undefined, .expr = undefined, + .rparen = undefined, }); try items.push(node); stack.append(State{ .AsmInputItems = items }) catch unreachable; try stack.append(State{ .IfToken = Token.Id.Comma }); - try stack.append(State{ .ExpectToken = Token.Id.RParen }); + try stack.append(State{ .ExpectTokenSave = ExpectTokenSave{ + .id = Token.Id.RParen, + .ptr = &node.rparen, + } }); try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.expr } }); try stack.append(State{ .ExpectToken = Token.Id.LParen }); try stack.append(State{ .StringLiteral = OptionalCtx{ .Required = &node.constraint } }); @@ -1187,10 +1178,6 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { } }, State.FieldInitListItemOrEnd => |list_state| { - while (try eatLineComment(arena, &tok_it, &tree)) |line_comment| { - try list_state.list.push(&line_comment.base); - } - if (eatToken(&tok_it, &tree, Token.Id.RBrace)) |rbrace| { (list_state.ptr).* = rbrace; continue; @@ -1248,10 +1235,6 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { } }, State.ErrorTagListItemOrEnd => |list_state| { - while (try eatLineComment(arena, &tok_it, &tree)) |line_comment| { - try list_state.list.push(&line_comment.base); - } - if (eatToken(&tok_it, &tree, Token.Id.RBrace)) |rbrace| { (list_state.ptr).* = rbrace; continue; @@ -1279,10 +1262,6 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { } }, State.SwitchCaseOrEnd => |list_state| { - while (try eatLineComment(arena, &tok_it, &tree)) |line_comment| { - try list_state.list.push(&line_comment.base); - } - if (eatToken(&tok_it, &tree, Token.Id.RBrace)) |rbrace| { (list_state.ptr).* = rbrace; continue; @@ -1294,12 +1273,13 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { .items = ast.Node.SwitchCase.ItemList.init(arena), .payload = null, .expr = undefined, + .arrow_token = undefined, }); try list_state.list.push(&node.base); try stack.append(State{ .SwitchCaseCommaOrEnd = list_state }); try stack.append(State{ .AssignmentExpressionBegin = OptionalCtx{ .Required = &node.expr } }); try stack.append(State{ .PointerPayload = OptionalCtx{ .Optional = &node.payload } }); - try stack.append(State{ .SwitchCaseFirstItem = &node.items }); + try stack.append(State{ .SwitchCaseFirstItem = node }); continue; }, @@ -1320,7 +1300,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { } }, - State.SwitchCaseFirstItem => |case_items| { + State.SwitchCaseFirstItem => |switch_case| { const token = nextToken(&tok_it, &tree); const token_index = token.index; const token_ptr = token.ptr; @@ -1329,25 +1309,30 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { .base = ast.Node{ .id = ast.Node.Id.SwitchElse }, .token = token_index, }); - try case_items.push(&else_node.base); + try switch_case.items.push(&else_node.base); - try stack.append(State{ .ExpectToken = Token.Id.EqualAngleBracketRight }); + try stack.append(State{ .ExpectTokenSave = ExpectTokenSave{ + .id = Token.Id.EqualAngleBracketRight, + .ptr = &switch_case.arrow_token, + } }); continue; } else { - putBackToken(&tok_it, &tree); - try stack.append(State{ .SwitchCaseItem = case_items }); + prevToken(&tok_it, &tree); + try stack.append(State{ .SwitchCaseItem = switch_case }); continue; } }, - State.SwitchCaseItem => |case_items| { - stack.append(State{ .SwitchCaseItemCommaOrEnd = case_items }) catch unreachable; - try stack.append(State{ .RangeExpressionBegin = OptionalCtx{ .Required = try case_items.addOne() } }); + State.SwitchCaseItem => |node| { + stack.append(State{ .SwitchCaseItemCommaOrEnd = node }) catch unreachable; + try stack.append(State{ .RangeExpressionBegin = OptionalCtx{ .Required = try node.items.addOne() } }); }, - State.SwitchCaseItemCommaOrEnd => |case_items| { + State.SwitchCaseItemCommaOrEnd => |node| { switch (expectCommaOrEnd(&tok_it, &tree, Token.Id.EqualAngleBracketRight)) { - ExpectCommaOrEndResult.end_token => |t| { - if (t == null) { - stack.append(State{ .SwitchCaseItem = case_items }) catch unreachable; + ExpectCommaOrEndResult.end_token => |end_token| { + if (end_token) |t| { + node.arrow_token = t; + } else { + stack.append(State{ .SwitchCaseItem = node }) catch unreachable; } continue; }, @@ -1429,8 +1414,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { stack.append(State{ .ContainerKind = ContainerKindCtx{ .opt_ctx = ctx.opt_ctx, - .ltoken = ctx.extern_token, - .layout = ast.Node.ContainerDecl.Layout.Extern, + .layout_token = ctx.extern_token, } }) catch unreachable; continue; }, @@ -1518,7 +1502,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { continue; }, else => { - putBackToken(&tok_it, &tree); + prevToken(&tok_it, &tree); continue; }, } @@ -1537,7 +1521,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { return tree; } - putBackToken(&tok_it, &tree); + prevToken(&tok_it, &tree); continue; } @@ -1569,7 +1553,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { return tree; } - putBackToken(&tok_it, &tree); + prevToken(&tok_it, &tree); continue; } @@ -1606,7 +1590,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { return tree; } - putBackToken(&tok_it, &tree); + prevToken(&tok_it, &tree); continue; } @@ -1691,7 +1675,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { }, else => { if (!try parseBlockExpr(&stack, arena, opt_ctx, token_ptr, token_index)) { - putBackToken(&tok_it, &tree); + prevToken(&tok_it, &tree); stack.append(State{ .UnwrapExpressionBegin = opt_ctx }) catch unreachable; } continue; @@ -1744,7 +1728,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.rhs } }); continue; } else { - putBackToken(&tok_it, &tree); + prevToken(&tok_it, &tree); continue; } }, @@ -1779,7 +1763,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { } continue; } else { - putBackToken(&tok_it, &tree); + prevToken(&tok_it, &tree); continue; } }, @@ -1857,7 +1841,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { try stack.append(State{ .BinaryOrExpressionBegin = OptionalCtx{ .Required = &node.rhs } }); continue; } else { - putBackToken(&tok_it, &tree); + prevToken(&tok_it, &tree); continue; } }, @@ -1959,7 +1943,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { try stack.append(State{ .AdditionExpressionBegin = OptionalCtx{ .Required = &node.rhs } }); continue; } else { - putBackToken(&tok_it, &tree); + prevToken(&tok_it, &tree); continue; } }, @@ -1989,7 +1973,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { try stack.append(State{ .MultiplyExpressionBegin = OptionalCtx{ .Required = &node.rhs } }); continue; } else { - putBackToken(&tok_it, &tree); + prevToken(&tok_it, &tree); continue; } }, @@ -2019,7 +2003,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { try stack.append(State{ .CurlySuffixExpressionBegin = OptionalCtx{ .Required = &node.rhs } }); continue; } else { - putBackToken(&tok_it, &tree); + prevToken(&tok_it, &tree); continue; } }, @@ -2124,7 +2108,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { } continue; } else { - putBackToken(&tok_it, &tree); + prevToken(&tok_it, &tree); stack.append(State{ .SuffixOpExpressionBegin = opt_ctx }) catch unreachable; continue; } @@ -2220,7 +2204,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { continue; }, else => { - putBackToken(&tok_it, &tree); + prevToken(&tok_it, &tree); continue; }, } @@ -2277,7 +2261,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { const next_token_index = next_token.index; const next_token_ptr = next_token.ptr; if (next_token_ptr.id != Token.Id.Arrow) { - putBackToken(&tok_it, &tree); + prevToken(&tok_it, &tree); continue; } node.result = ast.Node.PromiseType.Result{ @@ -2348,8 +2332,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { Token.Id.Keyword_packed => { stack.append(State{ .ContainerKind = ContainerKindCtx{ .opt_ctx = opt_ctx, - .ltoken = token.index, - .layout = ast.Node.ContainerDecl.Layout.Packed, + .layout_token = token.index, } }) catch unreachable; continue; }, @@ -2364,11 +2347,10 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { Token.Id.Keyword_struct, Token.Id.Keyword_union, Token.Id.Keyword_enum => { - putBackToken(&tok_it, &tree); + prevToken(&tok_it, &tree); stack.append(State{ .ContainerKind = ContainerKindCtx{ .opt_ctx = opt_ctx, - .ltoken = token.index, - .layout = ast.Node.ContainerDecl.Layout.Auto, + .layout_token = null, } }) catch unreachable; continue; }, @@ -2466,7 +2448,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { }, else => { if (!try parseBlockExpr(&stack, arena, opt_ctx, token.ptr, token.index)) { - putBackToken(&tok_it, &tree); + prevToken(&tok_it, &tree); if (opt_ctx != OptionalCtx.Optional) { ((try tree.errors.addOne())).* = Error{ .ExpectedPrimaryExpr = Error.ExpectedPrimaryExpr{ .token = token.index } }; return tree; @@ -2502,7 +2484,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { const token_index = token.index; const token_ptr = token.ptr; opt_ctx.store((try parseStringLiteral(arena, &tok_it, token_ptr, token_index, &tree)) ?? { - putBackToken(&tok_it, &tree); + prevToken(&tok_it, &tree); if (opt_ctx != OptionalCtx.Optional) { ((try tree.errors.addOne())).* = Error{ .ExpectedPrimaryExpr = Error.ExpectedPrimaryExpr{ .token = token_index } }; return tree; @@ -2576,7 +2558,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { } }; return tree; } - (expect_token_save.ptr).* = token_index; + expect_token_save.ptr.* = token_index; continue; }, State.IfToken => |token_id| { @@ -2645,8 +2627,7 @@ const ExternTypeCtx = struct { const ContainerKindCtx = struct { opt_ctx: OptionalCtx, - ltoken: TokenIndex, - layout: ast.Node.ContainerDecl.Layout, + layout_token: ?TokenIndex, }; const ExpectTokenSave = struct { @@ -2808,9 +2789,9 @@ const State = union(enum) { ErrorTagListCommaOrEnd: ListSave(ast.Node.ErrorSetDecl.DeclList), SwitchCaseOrEnd: ListSave(ast.Node.Switch.CaseList), SwitchCaseCommaOrEnd: ListSave(ast.Node.Switch.CaseList), - SwitchCaseFirstItem: &ast.Node.SwitchCase.ItemList, - SwitchCaseItem: &ast.Node.SwitchCase.ItemList, - SwitchCaseItemCommaOrEnd: &ast.Node.SwitchCase.ItemList, + SwitchCaseFirstItem: &ast.Node.SwitchCase, + SwitchCaseItem: &ast.Node.SwitchCase, + SwitchCaseItemCommaOrEnd: &ast.Node.SwitchCase, SuspendBody: &ast.Node.Suspend, AsyncAllocator: &ast.Node.AsyncAttribute, @@ -2899,14 +2880,6 @@ fn eatDocComments(arena: &mem.Allocator, tok_it: &ast.Tree.TokenList.Iterator, t return result; } -fn eatLineComment(arena: &mem.Allocator, tok_it: &ast.Tree.TokenList.Iterator, tree: &ast.Tree) !?&ast.Node.LineComment { - const token = eatToken(tok_it, tree, Token.Id.LineComment) ?? return null; - return try arena.construct(ast.Node.LineComment{ - .base = ast.Node{ .id = ast.Node.Id.LineComment }, - .token = token, - }); -} - fn parseStringLiteral(arena: &mem.Allocator, tok_it: &ast.Tree.TokenList.Iterator, token_ptr: &const Token, token_index: TokenIndex, tree: &ast.Tree) !?&ast.Node { switch (token_ptr.id) { Token.Id.StringLiteral => { @@ -2923,7 +2896,7 @@ fn parseStringLiteral(arena: &mem.Allocator, tok_it: &ast.Tree.TokenList.Iterato const multiline_str_index = multiline_str.index; const multiline_str_ptr = multiline_str.ptr; if (multiline_str_ptr.id != Token.Id.MultilineStringLiteralLine) { - putBackToken(tok_it, tree); + prevToken(tok_it, tree); break; } @@ -3176,11 +3149,12 @@ fn createToCtxLiteral(arena: &mem.Allocator, opt_ctx: &const OptionalCtx, compti } fn eatToken(tok_it: &ast.Tree.TokenList.Iterator, tree: &ast.Tree, id: @TagType(Token.Id)) ?TokenIndex { - const token = nextToken(tok_it, tree); + const token = ??tok_it.peek(); - if (token.ptr.id == id) return token.index; + if (token.id == id) { + return nextToken(tok_it, tree).index; + } - putBackToken(tok_it, tree); return null; } @@ -3189,27 +3163,20 @@ fn nextToken(tok_it: &ast.Tree.TokenList.Iterator, tree: &ast.Tree) AnnotatedTok .index = tok_it.index, .ptr = ??tok_it.next(), }; - // possibly skip a following same line token - const token = tok_it.next() ?? return result; - if (token.id != Token.Id.LineComment) { - putBackToken(tok_it, tree); - return result; + assert(result.ptr.id != Token.Id.LineComment); + + while (true) { + const next_tok = tok_it.peek() ?? return result; + if (next_tok.id != Token.Id.LineComment) return result; + _ = tok_it.next(); } - const loc = tree.tokenLocationPtr(result.ptr.end, token); - if (loc.line != 0) { - putBackToken(tok_it, tree); - } - return result; } -fn putBackToken(tok_it: &ast.Tree.TokenList.Iterator, tree: &ast.Tree) void { - const prev_tok = ??tok_it.prev(); - if (prev_tok.id == Token.Id.LineComment) { - const minus2_tok = tok_it.prev() ?? return; - const loc = tree.tokenLocationPtr(minus2_tok.end, prev_tok); - if (loc.line != 0) { - _ = tok_it.next(); - } +fn prevToken(tok_it: &ast.Tree.TokenList.Iterator, tree: &ast.Tree) void { + while (true) { + const prev_tok = tok_it.prev() ?? return; + if (prev_tok.id == Token.Id.LineComment) continue; + return; } } diff --git a/std/zig/parser_test.zig b/std/zig/parser_test.zig index 63d56167e83195c1e9674af9b664ab31d0485d4a..38ffee8aaf32412ab7996c3a1f082e4f9ffed788 100644 --- a/std/zig/parser_test.zig +++ b/std/zig/parser_test.zig @@ -1,3 +1,64 @@ +test "zig fmt: if-else end of comptime" { + try testCanonical( + \\comptime { + \\ if (a) { + \\ b(); + \\ } else { + \\ b(); + \\ } + \\} + \\ + ); +} + +test "zig fmt: nested blocks" { + try testCanonical( + \\comptime { + \\ { + \\ { + \\ { + \\ a(); + \\ } + \\ } + \\ } + \\} + \\ + ); +} + +test "zig fmt: block with same line comment after end brace" { + try testCanonical( + \\comptime { + \\ { + \\ b(); + \\ } // comment + \\} + \\ + ); +} + +test "zig fmt: statements with comment between" { + try testCanonical( + \\comptime { + \\ a = b; + \\ // comment + \\ a = b; + \\} + \\ + ); +} + +test "zig fmt: statements with empty line between" { + try testCanonical( + \\comptime { + \\ a = b; + \\ + \\ a = b; + \\} + \\ + ); +} + test "zig fmt: ptr deref operator" { try testCanonical( \\const a = b.*; @@ -7,6 +68,13 @@ test "zig fmt: ptr deref operator" { test "zig fmt: comment after if before another if" { try testCanonical( + \\test "aoeu" { + \\ // comment + \\ if (x) { + \\ bar(); + \\ } + \\} + \\ \\test "aoeu" { \\ if (x) { \\ foo(); @@ -21,7 +89,7 @@ test "zig fmt: comment after if before another if" { } test "zig fmt: line comment between if block and else keyword" { - try testTransform( + try testCanonical( \\test "aoeu" { \\ // cexp(finite|nan +- i inf|nan) = nan + i nan \\ if ((hx & 0x7fffffff) != 0x7f800000) { @@ -37,20 +105,6 @@ test "zig fmt: line comment between if block and else keyword" { \\ return Complex(f32).new(x, y - y); \\ } \\} - , - \\test "aoeu" { - \\ // cexp(finite|nan +- i inf|nan) = nan + i nan - \\ if ((hx & 0x7fffffff) != 0x7f800000) { - \\ return Complex(f32).new(y - y, y - y); - \\ } // cexp(-inf +- i inf|nan) = 0 + i0 - \\ else if (hx & 0x80000000 != 0) { - \\ return Complex(f32).new(0, 0); - \\ } // cexp(+inf +- i inf|nan) = inf + i nan - \\ // another comment - \\ else { - \\ return Complex(f32).new(x, y - y); - \\ } - \\} \\ ); } @@ -652,6 +706,11 @@ test "zig fmt: multiline string" { \\ c\\two) \\ c\\three \\ ; + \\ const s3 = // hi + \\ \\one + \\ \\two) + \\ \\three + \\ ; \\} \\ ); diff --git a/std/zig/render.zig b/std/zig/render.zig index 91e76e1c5f09208b448c3e9b658d2e4db4af3450..f48b13c987ef65970d5d1b752676be64ecbd83da 100644 --- a/std/zig/render.zig +++ b/std/zig/render.zig @@ -19,17 +19,21 @@ pub fn render(allocator: &mem.Allocator, stream: var, tree: &ast.Tree) (@typeOf( while (it.next()) |decl| { try renderTopLevelDecl(allocator, stream, tree, 0, decl.*); if (it.peek()) |next_decl| { - const n = if (nodeLineOffset(tree, decl.*, next_decl.*) >= 2) u8(2) else u8(1); - try stream.writeByteNTimes('\n', n); + try renderExtraNewline(tree, stream, next_decl.*); } } - try stream.write("\n"); } -fn nodeLineOffset(tree: &ast.Tree, a: &ast.Node, b: &ast.Node) usize { - const a_last_token = tree.tokens.at(a.lastToken()); - const loc = tree.tokenLocation(a_last_token.end, b.firstToken()); - return loc.line; +fn renderExtraNewline(tree: &ast.Tree, stream: var, node: &ast.Node) !void { + var first_token = node.firstToken(); + while (tree.tokens.at(first_token - 1).id == Token.Id.DocComment) { + first_token -= 1; + } + const prev_token_end = tree.tokens.at(first_token - 1).end; + const loc = tree.tokenLocation(prev_token_end, first_token); + if (loc.line >= 2) { + try stream.writeByte('\n'); + } } fn renderTopLevelDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent: usize, decl: &ast.Node) (@typeOf(stream).Child.Error || Error)!void { @@ -37,119 +41,124 @@ fn renderTopLevelDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, i ast.Node.Id.FnProto => { const fn_proto = @fieldParentPtr(ast.Node.FnProto, "base", decl); - try renderComments(tree, stream, fn_proto, indent); - try renderExpression(allocator, stream, tree, indent, decl); + try renderDocComments(tree, stream, fn_proto, indent); if (fn_proto.body_node) |body_node| { - try stream.write(" "); - try renderExpression(allocator, stream, tree, indent, body_node); + try renderExpression(allocator, stream, tree, indent, decl, Space.Space); + try renderExpression(allocator, stream, tree, indent, body_node, Space.Newline); } else { - try stream.write(";"); + try renderExpression(allocator, stream, tree, indent, decl, Space.None); + try renderToken(tree, stream, tree.nextToken(decl.lastToken()), indent, Space.Newline); } }, + ast.Node.Id.Use => { const use_decl = @fieldParentPtr(ast.Node.Use, "base", decl); if (use_decl.visib_token) |visib_token| { - try stream.print("{} ", tree.tokenSlice(visib_token)); + try renderToken(tree, stream, visib_token, indent, Space.Space); // pub } - try stream.write("use "); - try renderExpression(allocator, stream, tree, indent, use_decl.expr); - try stream.write(";"); + try renderToken(tree, stream, use_decl.use_token, indent, Space.Space); // use + try renderExpression(allocator, stream, tree, indent, use_decl.expr, Space.None); + try renderToken(tree, stream, use_decl.semicolon_token, indent, Space.Newline); // ; }, + ast.Node.Id.VarDecl => { const var_decl = @fieldParentPtr(ast.Node.VarDecl, "base", decl); - try renderComments(tree, stream, var_decl, indent); + try renderDocComments(tree, stream, var_decl, indent); try renderVarDecl(allocator, stream, tree, indent, var_decl); }, + ast.Node.Id.TestDecl => { const test_decl = @fieldParentPtr(ast.Node.TestDecl, "base", decl); - try renderComments(tree, stream, test_decl, indent); - try stream.write("test "); - try renderExpression(allocator, stream, tree, indent, test_decl.name); - try stream.write(" "); - try renderExpression(allocator, stream, tree, indent, test_decl.body_node); + try renderDocComments(tree, stream, test_decl, indent); + try renderToken(tree, stream, test_decl.test_token, indent, Space.Space); + try renderExpression(allocator, stream, tree, indent, test_decl.name, Space.Space); + try renderExpression(allocator, stream, tree, indent, test_decl.body_node, Space.Newline); }, + ast.Node.Id.StructField => { const field = @fieldParentPtr(ast.Node.StructField, "base", decl); - try renderComments(tree, stream, field, indent); + try renderDocComments(tree, stream, field, indent); if (field.visib_token) |visib_token| { - try stream.print("{} ", tree.tokenSlice(visib_token)); + try renderToken(tree, stream, visib_token, indent, Space.Space); // pub } - try stream.print("{}: ", tree.tokenSlice(field.name_token)); - try renderExpression(allocator, stream, tree, indent, field.type_expr); - try renderToken(tree, stream, field.lastToken() + 1, indent, true, true); + try renderToken(tree, stream, field.name_token, indent, Space.None); // name + try renderToken(tree, stream, tree.nextToken(field.name_token), indent, Space.Space); // : + try renderExpression(allocator, stream, tree, indent, field.type_expr, Space.None); // type + try renderToken(tree, stream, tree.nextToken(field.lastToken()), indent, Space.Newline); // , }, + ast.Node.Id.UnionTag => { const tag = @fieldParentPtr(ast.Node.UnionTag, "base", decl); - try renderComments(tree, stream, tag, indent); - try stream.print("{}", tree.tokenSlice(tag.name_token)); + try renderDocComments(tree, stream, tag, indent); + + const name_space = if (tag.type_expr == null and tag.value_expr != null) Space.Space else Space.None; + try renderToken(tree, stream, tag.name_token, indent, name_space); // name if (tag.type_expr) |type_expr| { - try stream.print(": "); - try renderExpression(allocator, stream, tree, indent, type_expr); + try renderToken(tree, stream, tree.nextToken(tag.name_token), indent, Space.Space); // : + + const after_type_space = if (tag.value_expr == null) Space.None else Space.Space; + try renderExpression(allocator, stream, tree, indent, type_expr, after_type_space); } if (tag.value_expr) |value_expr| { - try stream.print(" = "); - try renderExpression(allocator, stream, tree, indent, value_expr); + try renderToken(tree, stream, tree.prevToken(value_expr.firstToken()), indent, Space.Space); // = + try renderExpression(allocator, stream, tree, indent, value_expr, Space.None); } - try stream.write(","); + try renderToken(tree, stream, tree.nextToken(decl.lastToken()), indent, Space.Newline); // , }, + ast.Node.Id.EnumTag => { const tag = @fieldParentPtr(ast.Node.EnumTag, "base", decl); - try renderComments(tree, stream, tag, indent); - try stream.print("{}", tree.tokenSlice(tag.name_token)); + try renderDocComments(tree, stream, tag, indent); + + const after_name_space = if (tag.value == null) Space.None else Space.Space; + try renderToken(tree, stream, tag.name_token, indent, after_name_space); // name if (tag.value) |value| { - try stream.print(" = "); - try renderExpression(allocator, stream, tree, indent, value); + try renderToken(tree, stream, tree.nextToken(tag.name_token), indent, Space.Space); // = + try renderExpression(allocator, stream, tree, indent, value, Space.None); } - try stream.write(","); + try renderToken(tree, stream, tree.nextToken(decl.lastToken()), indent, Space.Newline); // , }, - ast.Node.Id.ErrorTag => { - const tag = @fieldParentPtr(ast.Node.ErrorTag, "base", decl); - try renderComments(tree, stream, tag, indent); - try stream.print("{}", tree.tokenSlice(tag.name_token)); - }, ast.Node.Id.Comptime => { - try renderExpression(allocator, stream, tree, indent, decl); - try maybeRenderSemicolon(stream, tree, indent, decl); - }, - ast.Node.Id.LineComment => { - const line_comment_node = @fieldParentPtr(ast.Node.LineComment, "base", decl); - - try stream.write(tree.tokenSlice(line_comment_node.token)); + assert(!decl.requireSemiColon()); + try renderExpression(allocator, stream, tree, indent, decl, Space.Newline); }, else => unreachable, } } -fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent: usize, base: &ast.Node) (@typeOf(stream).Child.Error || Error)!void { +fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent: usize, base: &ast.Node, space: Space) (@typeOf(stream).Child.Error || Error)!void { switch (base.id) { ast.Node.Id.Identifier => { const identifier = @fieldParentPtr(ast.Node.Identifier, "base", base); - try stream.print("{}", tree.tokenSlice(identifier.token)); + try renderToken(tree, stream, identifier.token, indent, space); }, ast.Node.Id.Block => { const block = @fieldParentPtr(ast.Node.Block, "base", base); + if (block.label) |label| { - try stream.print("{}: ", tree.tokenSlice(label)); + try renderToken(tree, stream, label, indent, Space.None); + try renderToken(tree, stream, tree.nextToken(label), indent, Space.Space); } if (block.statements.len == 0) { - try stream.write("{}"); + try renderToken(tree, stream, block.lbrace, indent + indent_delta, Space.None); + try renderToken(tree, stream, block.rbrace, indent, space); } else { - try stream.write("{\n"); const block_indent = indent + indent_delta; + try renderToken(tree, stream, block.lbrace, block_indent, Space.Newline); var it = block.statements.iterator(0); while (it.next()) |statement| { @@ -157,114 +166,85 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind try renderStatement(allocator, stream, tree, block_indent, statement.*); if (it.peek()) |next_statement| { - const n = if (nodeLineOffset(tree, statement.*, next_statement.*) >= 2) u8(2) else u8(1); - try stream.writeByteNTimes('\n', n); + try renderExtraNewline(tree, stream, next_statement.*); } } - try stream.write("\n"); try stream.writeByteNTimes(' ', indent); - try stream.write("}"); + try renderToken(tree, stream, block.rbrace, indent, space); } }, ast.Node.Id.Defer => { const defer_node = @fieldParentPtr(ast.Node.Defer, "base", base); - try stream.print("{} ", tree.tokenSlice(defer_node.defer_token)); - try renderExpression(allocator, stream, tree, indent, defer_node.expr); + + try renderToken(tree, stream, defer_node.defer_token, indent, Space.Space); + try renderExpression(allocator, stream, tree, indent, defer_node.expr, space); }, ast.Node.Id.Comptime => { const comptime_node = @fieldParentPtr(ast.Node.Comptime, "base", base); - try stream.print("{} ", tree.tokenSlice(comptime_node.comptime_token)); - try renderExpression(allocator, stream, tree, indent, comptime_node.expr); + + try renderToken(tree, stream, comptime_node.comptime_token, indent, Space.Space); + try renderExpression(allocator, stream, tree, indent, comptime_node.expr, space); }, + ast.Node.Id.AsyncAttribute => { const async_attr = @fieldParentPtr(ast.Node.AsyncAttribute, "base", base); - try stream.print("{}", tree.tokenSlice(async_attr.async_token)); if (async_attr.allocator_type) |allocator_type| { - try stream.write("<"); - try renderExpression(allocator, stream, tree, indent, allocator_type); - try stream.write(">"); + try renderToken(tree, stream, async_attr.async_token, indent, Space.None); + + try renderToken(tree, stream, tree.nextToken(async_attr.async_token), indent, Space.None); + try renderExpression(allocator, stream, tree, indent, allocator_type, Space.None); + try renderToken(tree, stream, tree.nextToken(allocator_type.lastToken()), indent, space); + } else { + try renderToken(tree, stream, async_attr.async_token, indent, space); } }, + ast.Node.Id.Suspend => { const suspend_node = @fieldParentPtr(ast.Node.Suspend, "base", base); + if (suspend_node.label) |label| { - try stream.print("{}: ", tree.tokenSlice(label)); + try renderToken(tree, stream, label, indent, Space.None); + try renderToken(tree, stream, tree.nextToken(label), indent, Space.Space); } - try stream.print("{}", tree.tokenSlice(suspend_node.suspend_token)); if (suspend_node.payload) |payload| { - try stream.write(" "); - try renderExpression(allocator, stream, tree, indent, payload); - } - - if (suspend_node.body) |body| { - try stream.write(" "); - try renderExpression(allocator, stream, tree, indent, body); + if (suspend_node.body) |body| { + try renderToken(tree, stream, suspend_node.suspend_token, indent, Space.Space); + try renderExpression(allocator, stream, tree, indent, payload, Space.Space); + try renderExpression(allocator, stream, tree, indent, body, space); + } else { + try renderToken(tree, stream, suspend_node.suspend_token, indent, Space.Space); + try renderExpression(allocator, stream, tree, indent, payload, space); + } + } else if (suspend_node.body) |body| { + try renderToken(tree, stream, suspend_node.suspend_token, indent, Space.Space); + try renderExpression(allocator, stream, tree, indent, body, space); + } else { + try renderToken(tree, stream, suspend_node.suspend_token, indent, space); } }, ast.Node.Id.InfixOp => { const infix_op_node = @fieldParentPtr(ast.Node.InfixOp, "base", base); - try renderExpression(allocator, stream, tree, indent, infix_op_node.lhs); - - const text = switch (infix_op_node.op) { - ast.Node.InfixOp.Op.Add => " + ", - ast.Node.InfixOp.Op.AddWrap => " +% ", - ast.Node.InfixOp.Op.ArrayCat => " ++ ", - ast.Node.InfixOp.Op.ArrayMult => " ** ", - ast.Node.InfixOp.Op.Assign => " = ", - ast.Node.InfixOp.Op.AssignBitAnd => " &= ", - ast.Node.InfixOp.Op.AssignBitOr => " |= ", - ast.Node.InfixOp.Op.AssignBitShiftLeft => " <<= ", - ast.Node.InfixOp.Op.AssignBitShiftRight => " >>= ", - ast.Node.InfixOp.Op.AssignBitXor => " ^= ", - ast.Node.InfixOp.Op.AssignDiv => " /= ", - ast.Node.InfixOp.Op.AssignMinus => " -= ", - ast.Node.InfixOp.Op.AssignMinusWrap => " -%= ", - ast.Node.InfixOp.Op.AssignMod => " %= ", - ast.Node.InfixOp.Op.AssignPlus => " += ", - ast.Node.InfixOp.Op.AssignPlusWrap => " +%= ", - ast.Node.InfixOp.Op.AssignTimes => " *= ", - ast.Node.InfixOp.Op.AssignTimesWarp => " *%= ", - ast.Node.InfixOp.Op.BangEqual => " != ", - ast.Node.InfixOp.Op.BitAnd => " & ", - ast.Node.InfixOp.Op.BitOr => " | ", - ast.Node.InfixOp.Op.BitShiftLeft => " << ", - ast.Node.InfixOp.Op.BitShiftRight => " >> ", - ast.Node.InfixOp.Op.BitXor => " ^ ", - ast.Node.InfixOp.Op.BoolAnd => " and ", - ast.Node.InfixOp.Op.BoolOr => " or ", - ast.Node.InfixOp.Op.Div => " / ", - ast.Node.InfixOp.Op.EqualEqual => " == ", - ast.Node.InfixOp.Op.ErrorUnion => "!", - ast.Node.InfixOp.Op.GreaterOrEqual => " >= ", - ast.Node.InfixOp.Op.GreaterThan => " > ", - ast.Node.InfixOp.Op.LessOrEqual => " <= ", - ast.Node.InfixOp.Op.LessThan => " < ", - ast.Node.InfixOp.Op.MergeErrorSets => " || ", - ast.Node.InfixOp.Op.Mod => " % ", - ast.Node.InfixOp.Op.Mult => " * ", - ast.Node.InfixOp.Op.MultWrap => " *% ", - ast.Node.InfixOp.Op.Period => ".", - ast.Node.InfixOp.Op.Sub => " - ", - ast.Node.InfixOp.Op.SubWrap => " -% ", - ast.Node.InfixOp.Op.UnwrapMaybe => " ?? ", - ast.Node.InfixOp.Op.Range => " ... ", - ast.Node.InfixOp.Op.Catch => |maybe_payload| blk: { - try stream.write(" catch "); - if (maybe_payload) |payload| { - try renderExpression(allocator, stream, tree, indent, payload); - try stream.write(" "); - } - break :blk ""; - }, + const op_token = tree.tokens.at(infix_op_node.op_token); + const op_space = switch (infix_op_node.op) { + ast.Node.InfixOp.Op.Period, ast.Node.InfixOp.Op.ErrorUnion => Space.None, + else => Space.Space, }; + try renderExpression(allocator, stream, tree, indent, infix_op_node.lhs, op_space); + try renderToken(tree, stream, infix_op_node.op_token, indent, op_space); - try stream.write(text); - try renderExpression(allocator, stream, tree, indent, infix_op_node.rhs); + switch (infix_op_node.op) { + ast.Node.InfixOp.Op.Catch => |maybe_payload| if (maybe_payload) |payload| { + try renderExpression(allocator, stream, tree, indent, payload, Space.Space); + }, + else => {}, + } + + try renderExpression(allocator, stream, tree, indent, infix_op_node.rhs, space); }, ast.Node.Id.PrefixOp => { @@ -272,52 +252,73 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind switch (prefix_op_node.op) { ast.Node.PrefixOp.Op.AddrOf => |addr_of_info| { - try stream.write("&"); + try renderToken(tree, stream, prefix_op_node.op_token, indent, Space.None); // & if (addr_of_info.align_expr) |align_expr| { - try stream.write("align("); - try renderExpression(allocator, stream, tree, indent, align_expr); - try stream.write(") "); + const align_token = tree.nextToken(prefix_op_node.op_token); + try renderToken(tree, stream, align_token, indent, Space.None); // align + + const lparen_token = tree.prevToken(align_expr.firstToken()); + try renderToken(tree, stream, lparen_token, indent, Space.None); // ( + + try renderExpression(allocator, stream, tree, indent, align_expr, Space.None); + + const rparen_token = tree.nextToken(align_expr.lastToken()); + try renderToken(tree, stream, rparen_token, indent, Space.Space); // ) } - if (addr_of_info.const_token != null) { - try stream.write("const "); + if (addr_of_info.const_token) |const_token| { + try renderToken(tree, stream, const_token, indent, Space.Space); // const } - if (addr_of_info.volatile_token != null) { - try stream.write("volatile "); + if (addr_of_info.volatile_token) |volatile_token| { + try renderToken(tree, stream, volatile_token, indent, Space.Space); // volatile } }, ast.Node.PrefixOp.Op.SliceType => |addr_of_info| { - try stream.write("[]"); + try renderToken(tree, stream, prefix_op_node.op_token, indent, Space.None); // [ + try renderToken(tree, stream, tree.nextToken(prefix_op_node.op_token), indent, Space.None); // ] + if (addr_of_info.align_expr) |align_expr| { - try stream.print("align("); - try renderExpression(allocator, stream, tree, indent, align_expr); - try stream.print(") "); + const align_token = tree.nextToken(prefix_op_node.op_token); + try renderToken(tree, stream, align_token, indent, Space.None); // align + + const lparen_token = tree.prevToken(align_expr.firstToken()); + try renderToken(tree, stream, lparen_token, indent, Space.None); // ( + + try renderExpression(allocator, stream, tree, indent, align_expr, Space.None); + + const rparen_token = tree.nextToken(align_expr.lastToken()); + try renderToken(tree, stream, rparen_token, indent, Space.Space); // ) } - if (addr_of_info.const_token != null) { - try stream.print("const "); + if (addr_of_info.const_token) |const_token| { + try renderToken(tree, stream, const_token, indent, Space.Space); } - if (addr_of_info.volatile_token != null) { - try stream.print("volatile "); + if (addr_of_info.volatile_token) |volatile_token| { + try renderToken(tree, stream, volatile_token, indent, Space.Space); } }, ast.Node.PrefixOp.Op.ArrayType => |array_index| { - try stream.print("["); - try renderExpression(allocator, stream, tree, indent, array_index); - try stream.print("]"); + try renderToken(tree, stream, prefix_op_node.op_token, indent, Space.None); // [ + try renderExpression(allocator, stream, tree, indent, array_index, Space.None); + try renderToken(tree, stream, tree.nextToken(array_index.lastToken()), indent, Space.None); // ] + }, + ast.Node.PrefixOp.Op.BitNot, + ast.Node.PrefixOp.Op.BoolNot, + ast.Node.PrefixOp.Op.Negation, + ast.Node.PrefixOp.Op.NegationWrap, + ast.Node.PrefixOp.Op.UnwrapMaybe, + ast.Node.PrefixOp.Op.MaybeType, + ast.Node.PrefixOp.Op.PointerType => { + try renderToken(tree, stream, prefix_op_node.op_token, indent, Space.None); + }, + + ast.Node.PrefixOp.Op.Try, + ast.Node.PrefixOp.Op.Await, + ast.Node.PrefixOp.Op.Cancel, + ast.Node.PrefixOp.Op.Resume => { + try renderToken(tree, stream, prefix_op_node.op_token, indent, Space.Space); }, - ast.Node.PrefixOp.Op.BitNot => try stream.write("~"), - ast.Node.PrefixOp.Op.BoolNot => try stream.write("!"), - ast.Node.PrefixOp.Op.Negation => try stream.write("-"), - ast.Node.PrefixOp.Op.NegationWrap => try stream.write("-%"), - ast.Node.PrefixOp.Op.Try => try stream.write("try "), - ast.Node.PrefixOp.Op.UnwrapMaybe => try stream.write("??"), - ast.Node.PrefixOp.Op.MaybeType => try stream.write("?"), - ast.Node.PrefixOp.Op.PointerType => try stream.write("*"), - ast.Node.PrefixOp.Op.Await => try stream.write("await "), - ast.Node.PrefixOp.Op.Cancel => try stream.write("cancel "), - ast.Node.PrefixOp.Op.Resume => try stream.write("resume "), } - try renderExpression(allocator, stream, tree, indent, prefix_op_node.rhs); + try renderExpression(allocator, stream, tree, indent, prefix_op_node.rhs, space); }, ast.Node.Id.SuffixOp => { @@ -326,123 +327,139 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind switch (suffix_op.op) { @TagType(ast.Node.SuffixOp.Op).Call => |*call_info| { if (call_info.async_attr) |async_attr| { - try renderExpression(allocator, stream, tree, indent, &async_attr.base); - try stream.write(" "); + try renderExpression(allocator, stream, tree, indent, &async_attr.base, Space.Space); } - try renderExpression(allocator, stream, tree, indent, suffix_op.lhs); - try stream.write("("); + try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None); + + const lparen = tree.nextToken(suffix_op.lhs.lastToken()); + try renderToken(tree, stream, lparen, indent, Space.None); var it = call_info.params.iterator(0); while (it.next()) |param_node| { - try renderExpression(allocator, stream, tree, indent, param_node.*); + try renderExpression(allocator, stream, tree, indent, param_node.*, Space.None); + if (it.peek() != null) { - try stream.write(", "); + const comma = tree.nextToken(param_node.*.lastToken()); + try renderToken(tree, stream, comma, indent, Space.Space); } } - try stream.write(")"); + try renderToken(tree, stream, suffix_op.rtoken, indent, space); }, ast.Node.SuffixOp.Op.ArrayAccess => |index_expr| { - try renderExpression(allocator, stream, tree, indent, suffix_op.lhs); - try stream.write("["); - try renderExpression(allocator, stream, tree, indent, index_expr); - try stream.write("]"); + const lbracket = tree.prevToken(index_expr.firstToken()); + const rbracket = tree.nextToken(index_expr.lastToken()); + + try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None); + try renderToken(tree, stream, lbracket, indent, Space.None); // [ + try renderExpression(allocator, stream, tree, indent, index_expr, Space.None); + try renderToken(tree, stream, rbracket, indent, space); // ] }, ast.Node.SuffixOp.Op.Deref => { - try renderExpression(allocator, stream, tree, indent, suffix_op.lhs); - try stream.write(".*"); + try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None); + try renderToken(tree, stream, tree.prevToken(suffix_op.rtoken), indent, Space.None); // . + try renderToken(tree, stream, suffix_op.rtoken, indent, space); // * }, @TagType(ast.Node.SuffixOp.Op).Slice => |range| { - try renderExpression(allocator, stream, tree, indent, suffix_op.lhs); - try stream.write("["); - try renderExpression(allocator, stream, tree, indent, range.start); - try stream.write(".."); + try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None); + + const lbracket = tree.prevToken(range.start.firstToken()); + const dotdot = tree.nextToken(range.start.lastToken()); + + try renderToken(tree, stream, lbracket, indent, Space.None); // [ + try renderExpression(allocator, stream, tree, indent, range.start, Space.None); + try renderToken(tree, stream, dotdot, indent, Space.None); // .. if (range.end) |end| { - try renderExpression(allocator, stream, tree, indent, end); + try renderExpression(allocator, stream, tree, indent, end, Space.None); } - try stream.write("]"); + try renderToken(tree, stream, suffix_op.rtoken, indent, space); // ] }, ast.Node.SuffixOp.Op.StructInitializer => |*field_inits| { + const lbrace = tree.nextToken(suffix_op.lhs.lastToken()); + if (field_inits.len == 0) { - try renderExpression(allocator, stream, tree, indent, suffix_op.lhs); - try stream.write("{}"); + try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None); + try renderToken(tree, stream, lbrace, indent, Space.None); + try renderToken(tree, stream, suffix_op.rtoken, indent, space); return; } if (field_inits.len == 1) { const field_init = field_inits.at(0).*; - try renderExpression(allocator, stream, tree, indent, suffix_op.lhs); - try stream.write("{ "); - try renderExpression(allocator, stream, tree, indent, field_init); - try stream.write(" }"); + try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None); + try renderToken(tree, stream, lbrace, indent, Space.Space); + try renderExpression(allocator, stream, tree, indent, field_init, Space.Space); + try renderToken(tree, stream, suffix_op.rtoken, indent, space); return; } - try renderExpression(allocator, stream, tree, indent, suffix_op.lhs); - try stream.write("{\n"); + try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None); + try renderToken(tree, stream, lbrace, indent, Space.Newline); const new_indent = indent + indent_delta; var it = field_inits.iterator(0); while (it.next()) |field_init| { try stream.writeByteNTimes(' ', new_indent); - try renderExpression(allocator, stream, tree, new_indent, field_init.*); - if ((field_init.*).id != ast.Node.Id.LineComment) { - try stream.write(","); - } + try renderExpression(allocator, stream, tree, new_indent, field_init.*, Space.None); + + const comma = tree.nextToken(field_init.*.lastToken()); + try renderToken(tree, stream, comma, new_indent, Space.Newline); + if (it.peek()) |next_field_init| { - const n = if (nodeLineOffset(tree, field_init.*, next_field_init.*) >= 2) u8(2) else u8(1); - try stream.writeByteNTimes('\n', n); + try renderExtraNewline(tree, stream, next_field_init.*); } } - try stream.write("\n"); try stream.writeByteNTimes(' ', indent); - try stream.write("}"); + try renderToken(tree, stream, suffix_op.rtoken, indent, space); }, ast.Node.SuffixOp.Op.ArrayInitializer => |*exprs| { + const lbrace = tree.nextToken(suffix_op.lhs.lastToken()); + if (exprs.len == 0) { - try renderExpression(allocator, stream, tree, indent, suffix_op.lhs); - try stream.write("{}"); + try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None); + try renderToken(tree, stream, lbrace, indent, Space.None); + try renderToken(tree, stream, suffix_op.rtoken, indent, space); return; } if (exprs.len == 1) { const expr = exprs.at(0).*; - try renderExpression(allocator, stream, tree, indent, suffix_op.lhs); - try stream.write("{"); - try renderExpression(allocator, stream, tree, indent, expr); - try stream.write("}"); + try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None); + try renderToken(tree, stream, lbrace, indent, Space.None); + try renderExpression(allocator, stream, tree, indent, expr, Space.None); + try renderToken(tree, stream, suffix_op.rtoken, indent, space); return; } - try renderExpression(allocator, stream, tree, indent, suffix_op.lhs); + try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None); const new_indent = indent + indent_delta; - try stream.write("{\n"); + try renderToken(tree, stream, lbrace, new_indent, Space.Newline); var it = exprs.iterator(0); while (it.next()) |expr| { try stream.writeByteNTimes(' ', new_indent); - try renderExpression(allocator, stream, tree, new_indent, expr.*); - try stream.write(","); + try renderExpression(allocator, stream, tree, new_indent, expr.*, Space.None); + + const comma = tree.nextToken(expr.*.lastToken()); + try renderToken(tree, stream, comma, new_indent, Space.Newline); // , if (it.peek()) |next_expr| { - const n = if (nodeLineOffset(tree, expr.*, next_expr.*) >= 2) u8(2) else u8(1); - try stream.writeByteNTimes('\n', n); + try renderExtraNewline(tree, stream, next_expr.*); } } - try stream.write("\n"); try stream.writeByteNTimes(' ', indent); - try stream.write("}"); + try renderToken(tree, stream, suffix_op.rtoken, indent, space); }, } }, @@ -452,159 +469,182 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind switch (flow_expr.kind) { ast.Node.ControlFlowExpression.Kind.Break => |maybe_label| { - try stream.print("break"); + const kw_space = if (maybe_label != null or flow_expr.rhs != null) Space.Space else space; + try renderToken(tree, stream, flow_expr.ltoken, indent, kw_space); if (maybe_label) |label| { - try stream.print(" :"); - try renderExpression(allocator, stream, tree, indent, label); + const colon = tree.nextToken(flow_expr.ltoken); + try renderToken(tree, stream, colon, indent, Space.None); + + const expr_space = if (flow_expr.rhs != null) Space.Space else space; + try renderExpression(allocator, stream, tree, indent, label, expr_space); } }, ast.Node.ControlFlowExpression.Kind.Continue => |maybe_label| { - try stream.print("continue"); + const kw_space = if (maybe_label != null or flow_expr.rhs != null) Space.Space else space; + try renderToken(tree, stream, flow_expr.ltoken, indent, kw_space); if (maybe_label) |label| { - try stream.print(" :"); - try renderExpression(allocator, stream, tree, indent, label); + const colon = tree.nextToken(flow_expr.ltoken); + try renderToken(tree, stream, colon, indent, Space.None); + + const expr_space = if (flow_expr.rhs != null) Space.Space else space; + try renderExpression(allocator, stream, tree, indent, label, space); } }, ast.Node.ControlFlowExpression.Kind.Return => { - try stream.print("return"); + const kw_space = if (flow_expr.rhs != null) Space.Space else space; + try renderToken(tree, stream, flow_expr.ltoken, indent, kw_space); }, } if (flow_expr.rhs) |rhs| { - try stream.write(" "); - try renderExpression(allocator, stream, tree, indent, rhs); + try renderExpression(allocator, stream, tree, indent, rhs, space); } }, ast.Node.Id.Payload => { const payload = @fieldParentPtr(ast.Node.Payload, "base", base); - try stream.write("|"); - try renderExpression(allocator, stream, tree, indent, payload.error_symbol); - try stream.write("|"); + try renderToken(tree, stream, payload.lpipe, indent, Space.None); + try renderExpression(allocator, stream, tree, indent, payload.error_symbol, Space.None); + try renderToken(tree, stream, payload.rpipe, indent, space); }, ast.Node.Id.PointerPayload => { const payload = @fieldParentPtr(ast.Node.PointerPayload, "base", base); - try stream.write("|"); + try renderToken(tree, stream, payload.lpipe, indent, Space.None); if (payload.ptr_token) |ptr_token| { - try stream.write(tree.tokenSlice(ptr_token)); + try renderToken(tree, stream, ptr_token, indent, Space.None); } - try renderExpression(allocator, stream, tree, indent, payload.value_symbol); - try stream.write("|"); + try renderExpression(allocator, stream, tree, indent, payload.value_symbol, Space.None); + try renderToken(tree, stream, payload.rpipe, indent, space); }, ast.Node.Id.PointerIndexPayload => { const payload = @fieldParentPtr(ast.Node.PointerIndexPayload, "base", base); - try stream.write("|"); + try renderToken(tree, stream, payload.lpipe, indent, Space.None); if (payload.ptr_token) |ptr_token| { - try stream.write(tree.tokenSlice(ptr_token)); + try renderToken(tree, stream, ptr_token, indent, Space.None); } - try renderExpression(allocator, stream, tree, indent, payload.value_symbol); + try renderExpression(allocator, stream, tree, indent, payload.value_symbol, Space.None); if (payload.index_symbol) |index_symbol| { - try stream.write(", "); - try renderExpression(allocator, stream, tree, indent, index_symbol); + const comma = tree.nextToken(payload.value_symbol.lastToken()); + + try renderToken(tree, stream, comma, indent, Space.Space); + try renderExpression(allocator, stream, tree, indent, index_symbol, Space.None); } - try stream.write("|"); + try renderToken(tree, stream, payload.rpipe, indent, space); }, ast.Node.Id.GroupedExpression => { const grouped_expr = @fieldParentPtr(ast.Node.GroupedExpression, "base", base); - try renderToken(tree, stream, grouped_expr.lparen, indent, false, false); - try renderExpression(allocator, stream, tree, indent, grouped_expr.expr); - try renderToken(tree, stream, grouped_expr.rparen, indent, false, false); + try renderToken(tree, stream, grouped_expr.lparen, indent, Space.None); + try renderExpression(allocator, stream, tree, indent, grouped_expr.expr, Space.None); + try renderToken(tree, stream, grouped_expr.rparen, indent, space); }, ast.Node.Id.FieldInitializer => { const field_init = @fieldParentPtr(ast.Node.FieldInitializer, "base", base); - try stream.print(".{} = ", tree.tokenSlice(field_init.name_token)); - try renderExpression(allocator, stream, tree, indent, field_init.expr); + try renderToken(tree, stream, field_init.period_token, indent, Space.None); // . + try renderToken(tree, stream, field_init.name_token, indent, Space.Space); // name + try renderToken(tree, stream, tree.nextToken(field_init.name_token), indent, Space.Space); // = + try renderExpression(allocator, stream, tree, indent, field_init.expr, space); }, ast.Node.Id.IntegerLiteral => { const integer_literal = @fieldParentPtr(ast.Node.IntegerLiteral, "base", base); - try renderToken(tree, stream, integer_literal.token, indent, false, false); + try renderToken(tree, stream, integer_literal.token, indent, space); }, ast.Node.Id.FloatLiteral => { const float_literal = @fieldParentPtr(ast.Node.FloatLiteral, "base", base); - try stream.print("{}", tree.tokenSlice(float_literal.token)); + try renderToken(tree, stream, float_literal.token, indent, space); }, ast.Node.Id.StringLiteral => { const string_literal = @fieldParentPtr(ast.Node.StringLiteral, "base", base); - try renderToken(tree, stream, string_literal.token, indent, false, false); + try renderToken(tree, stream, string_literal.token, indent, space); }, ast.Node.Id.CharLiteral => { const char_literal = @fieldParentPtr(ast.Node.CharLiteral, "base", base); - try stream.print("{}", tree.tokenSlice(char_literal.token)); + try renderToken(tree, stream, char_literal.token, indent, space); }, ast.Node.Id.BoolLiteral => { const bool_literal = @fieldParentPtr(ast.Node.CharLiteral, "base", base); - try stream.print("{}", tree.tokenSlice(bool_literal.token)); + try renderToken(tree, stream, bool_literal.token, indent, space); }, ast.Node.Id.NullLiteral => { const null_literal = @fieldParentPtr(ast.Node.NullLiteral, "base", base); - try stream.print("{}", tree.tokenSlice(null_literal.token)); + try renderToken(tree, stream, null_literal.token, indent, space); }, ast.Node.Id.ThisLiteral => { const this_literal = @fieldParentPtr(ast.Node.ThisLiteral, "base", base); - try stream.print("{}", tree.tokenSlice(this_literal.token)); + try renderToken(tree, stream, this_literal.token, indent, space); }, ast.Node.Id.Unreachable => { const unreachable_node = @fieldParentPtr(ast.Node.Unreachable, "base", base); - try stream.print("{}", tree.tokenSlice(unreachable_node.token)); + try renderToken(tree, stream, unreachable_node.token, indent, space); }, ast.Node.Id.ErrorType => { const error_type = @fieldParentPtr(ast.Node.ErrorType, "base", base); - try stream.print("{}", tree.tokenSlice(error_type.token)); + try renderToken(tree, stream, error_type.token, indent, space); }, ast.Node.Id.VarType => { const var_type = @fieldParentPtr(ast.Node.VarType, "base", base); - try stream.print("{}", tree.tokenSlice(var_type.token)); + try renderToken(tree, stream, var_type.token, indent, space); }, ast.Node.Id.ContainerDecl => { const container_decl = @fieldParentPtr(ast.Node.ContainerDecl, "base", base); - switch (container_decl.layout) { - ast.Node.ContainerDecl.Layout.Packed => try stream.print("packed "), - ast.Node.ContainerDecl.Layout.Extern => try stream.print("extern "), - ast.Node.ContainerDecl.Layout.Auto => {}, - } - - switch (container_decl.kind) { - ast.Node.ContainerDecl.Kind.Struct => try stream.print("struct"), - ast.Node.ContainerDecl.Kind.Enum => try stream.print("enum"), - ast.Node.ContainerDecl.Kind.Union => try stream.print("union"), + if (container_decl.layout_token) |layout_token| { + try renderToken(tree, stream, layout_token, indent, Space.Space); } switch (container_decl.init_arg_expr) { - ast.Node.ContainerDecl.InitArg.None => try stream.write(" "), + ast.Node.ContainerDecl.InitArg.None => { + try renderToken(tree, stream, container_decl.kind_token, indent, Space.Space); // union + }, ast.Node.ContainerDecl.InitArg.Enum => |enum_tag_type| { + try renderToken(tree, stream, container_decl.kind_token, indent, Space.None); // union + + const lparen = tree.nextToken(container_decl.kind_token); + const enum_token = tree.nextToken(lparen); + + try renderToken(tree, stream, lparen, indent, Space.None); // ( + try renderToken(tree, stream, enum_token, indent, Space.None); // enum + if (enum_tag_type) |expr| { - try stream.write("(enum("); - try renderExpression(allocator, stream, tree, indent, expr); - try stream.write(")) "); + try renderToken(tree, stream, tree.nextToken(enum_token), indent, Space.None); // ( + try renderExpression(allocator, stream, tree, indent, expr, Space.None); + + const rparen = tree.nextToken(expr.lastToken()); + try renderToken(tree, stream, rparen, indent, Space.None); // ) + try renderToken(tree, stream, tree.nextToken(rparen), indent, Space.Space); // ) } else { - try stream.write("(enum) "); + try renderToken(tree, stream, tree.nextToken(enum_token), indent, Space.Space); // ) } }, ast.Node.ContainerDecl.InitArg.Type => |type_expr| { - try stream.write("("); - try renderExpression(allocator, stream, tree, indent, type_expr); - try stream.write(") "); + try renderToken(tree, stream, container_decl.kind_token, indent, Space.None); // union + + const lparen = tree.nextToken(container_decl.kind_token); + const rparen = tree.nextToken(type_expr.lastToken()); + + try renderToken(tree, stream, lparen, indent, Space.None); // ( + try renderExpression(allocator, stream, tree, indent, type_expr, Space.None); + try renderToken(tree, stream, rparen, indent, Space.Space); // ) }, } if (container_decl.fields_and_decls.len == 0) { - try stream.write("{}"); + try renderToken(tree, stream, container_decl.lbrace_token, indent + indent_delta, Space.None); // { + try renderToken(tree, stream, container_decl.rbrace_token, indent, space); // } } else { - try stream.write("{\n"); const new_indent = indent + indent_delta; + try renderToken(tree, stream, container_decl.lbrace_token, new_indent, Space.Newline); // { var it = container_decl.fields_and_decls.iterator(0); while (it.next()) |decl| { @@ -612,22 +652,24 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind try renderTopLevelDecl(allocator, stream, tree, new_indent, decl.*); if (it.peek()) |next_decl| { - const n = if (nodeLineOffset(tree, decl.*, next_decl.*) >= 2) u8(2) else u8(1); - try stream.writeByteNTimes('\n', n); + try renderExtraNewline(tree, stream, next_decl.*); } } - try stream.write("\n"); try stream.writeByteNTimes(' ', indent); - try stream.write("}"); + try renderToken(tree, stream, container_decl.rbrace_token, indent, space); // } } }, ast.Node.Id.ErrorSetDecl => { const err_set_decl = @fieldParentPtr(ast.Node.ErrorSetDecl, "base", base); + const lbrace = tree.nextToken(err_set_decl.error_token); + if (err_set_decl.decls.len == 0) { - try stream.write("error{}"); + try renderToken(tree, stream, err_set_decl.error_token, indent, Space.None); + try renderToken(tree, stream, lbrace, indent, Space.None); + try renderToken(tree, stream, err_set_decl.rbrace_token, indent, space); return; } @@ -642,62 +684,80 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind break :blk; } - try stream.write("error{"); - try renderTopLevelDecl(allocator, stream, tree, indent, node); - try stream.write("}"); + try renderToken(tree, stream, err_set_decl.error_token, indent, Space.None); // error + try renderToken(tree, stream, lbrace, indent, Space.None); // { + try renderExpression(allocator, stream, tree, indent, node, Space.None); + try renderToken(tree, stream, err_set_decl.rbrace_token, indent, space); // } return; } - try stream.write("error{\n"); + try renderToken(tree, stream, err_set_decl.error_token, indent, Space.None); // error + try renderToken(tree, stream, lbrace, indent, Space.Newline); // { const new_indent = indent + indent_delta; var it = err_set_decl.decls.iterator(0); while (it.next()) |node| { try stream.writeByteNTimes(' ', new_indent); - try renderTopLevelDecl(allocator, stream, tree, new_indent, node.*); - if ((node.*).id != ast.Node.Id.LineComment) { - try stream.write(","); - } + try renderExpression(allocator, stream, tree, new_indent, node.*, Space.None); + try renderToken(tree, stream, tree.nextToken(node.*.lastToken()), new_indent, Space.Newline); // , + if (it.peek()) |next_node| { - const n = if (nodeLineOffset(tree, node.*, next_node.*) >= 2) u8(2) else u8(1); - try stream.writeByteNTimes('\n', n); + try renderExtraNewline(tree, stream, next_node.*); } } - try stream.write("\n"); try stream.writeByteNTimes(' ', indent); - try stream.write("}"); + try renderToken(tree, stream, err_set_decl.rbrace_token, indent, space); // } + }, + + ast.Node.Id.ErrorTag => { + const tag = @fieldParentPtr(ast.Node.ErrorTag, "base", base); + + try renderDocComments(tree, stream, tag, indent); + try renderToken(tree, stream, tag.name_token, indent, space); // name }, ast.Node.Id.MultilineStringLiteral => { const multiline_str_literal = @fieldParentPtr(ast.Node.MultilineStringLiteral, "base", base); - try stream.print("\n"); + + var skip_first_indent = true; + if (tree.tokens.at(multiline_str_literal.firstToken() - 1).id != Token.Id.LineComment) { + try stream.print("\n"); + skip_first_indent = false; + } var i: usize = 0; while (i < multiline_str_literal.lines.len) : (i += 1) { const t = multiline_str_literal.lines.at(i).*; - try stream.writeByteNTimes(' ', indent + indent_delta); - try stream.print("{}", tree.tokenSlice(t)); + if (!skip_first_indent) { + try stream.writeByteNTimes(' ', indent + indent_delta); + } + try renderToken(tree, stream, t, indent, Space.None); + skip_first_indent = false; } try stream.writeByteNTimes(' ', indent); }, ast.Node.Id.UndefinedLiteral => { const undefined_literal = @fieldParentPtr(ast.Node.UndefinedLiteral, "base", base); - try stream.print("{}", tree.tokenSlice(undefined_literal.token)); + try renderToken(tree, stream, undefined_literal.token, indent, space); }, ast.Node.Id.BuiltinCall => { const builtin_call = @fieldParentPtr(ast.Node.BuiltinCall, "base", base); - try stream.print("{}(", tree.tokenSlice(builtin_call.builtin_token)); + + try renderToken(tree, stream, builtin_call.builtin_token, indent, Space.None); // @name + try renderToken(tree, stream, tree.nextToken(builtin_call.builtin_token), indent, Space.None); // ( var it = builtin_call.params.iterator(0); while (it.next()) |param_node| { - try renderExpression(allocator, stream, tree, indent, param_node.*); + try renderExpression(allocator, stream, tree, indent, param_node.*, Space.None); + if (it.peek() != null) { - try stream.write(", "); + const comma_token = tree.nextToken(param_node.*.lastToken()); + try renderToken(tree, stream, comma_token, indent, Space.Space); // , } } - try stream.write(")"); + try renderToken(tree, stream, builtin_call.rparen_token, indent, space); // ) }, ast.Node.Id.FnProto => { @@ -706,108 +766,123 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind if (fn_proto.visib_token) |visib_token_index| { const visib_token = tree.tokens.at(visib_token_index); assert(visib_token.id == Token.Id.Keyword_pub or visib_token.id == Token.Id.Keyword_export); - try stream.print("{} ", tree.tokenSlice(visib_token_index)); + + try renderToken(tree, stream, visib_token_index, indent, Space.Space); // pub } if (fn_proto.extern_export_inline_token) |extern_export_inline_token| { - try stream.print("{} ", tree.tokenSlice(extern_export_inline_token)); + try renderToken(tree, stream, extern_export_inline_token, indent, Space.Space); // extern/export } if (fn_proto.lib_name) |lib_name| { - try renderExpression(allocator, stream, tree, indent, lib_name); - try stream.write(" "); + try renderExpression(allocator, stream, tree, indent, lib_name, Space.Space); } if (fn_proto.cc_token) |cc_token| { - try stream.print("{} ", tree.tokenSlice(cc_token)); + try renderToken(tree, stream, cc_token, indent, Space.Space); // stdcallcc } if (fn_proto.async_attr) |async_attr| { - try renderExpression(allocator, stream, tree, indent, &async_attr.base); - try stream.write(" "); + try renderExpression(allocator, stream, tree, indent, &async_attr.base, Space.Space); } - try stream.write("fn"); - - if (fn_proto.name_token) |name_token| { - try stream.print(" {}", tree.tokenSlice(name_token)); + if (fn_proto.name_token) |name_token| blk: { + try renderToken(tree, stream, fn_proto.fn_token, indent, Space.Space); // fn + try renderToken(tree, stream, name_token, indent, Space.None); // name + try renderToken(tree, stream, tree.nextToken(name_token), indent, Space.None); // ( + } else blk: { + try renderToken(tree, stream, fn_proto.fn_token, indent, Space.None); // fn + try renderToken(tree, stream, tree.nextToken(fn_proto.fn_token), indent, Space.None); // ( } - try stream.write("("); - var it = fn_proto.params.iterator(0); while (it.next()) |param_decl_node| { try renderParamDecl(allocator, stream, tree, indent, param_decl_node.*); if (it.peek() != null) { - try stream.write(", "); + const comma = tree.nextToken(param_decl_node.*.lastToken()); + try renderToken(tree, stream, comma, indent, Space.Space); // , } } - try stream.write(") "); + const rparen = tree.prevToken(switch (fn_proto.return_type) { + ast.Node.FnProto.ReturnType.Explicit => |node| node.firstToken(), + ast.Node.FnProto.ReturnType.InferErrorSet => |node| tree.prevToken(node.firstToken()), + }); + try renderToken(tree, stream, rparen, indent, Space.Space); // ) if (fn_proto.align_expr) |align_expr| { - try stream.write("align("); - try renderExpression(allocator, stream, tree, indent, align_expr); - try stream.write(") "); + const align_rparen = tree.nextToken(align_expr.lastToken()); + const align_lparen = tree.prevToken(align_expr.firstToken()); + const align_kw = tree.prevToken(align_lparen); + + try renderToken(tree, stream, align_kw, indent, Space.None); // align + try renderToken(tree, stream, align_lparen, indent, Space.None); // ( + try renderExpression(allocator, stream, tree, indent, align_expr, Space.None); + try renderToken(tree, stream, align_rparen, indent, Space.Space); // ) } switch (fn_proto.return_type) { ast.Node.FnProto.ReturnType.Explicit => |node| { - try renderExpression(allocator, stream, tree, indent, node); + try renderExpression(allocator, stream, tree, indent, node, space); }, ast.Node.FnProto.ReturnType.InferErrorSet => |node| { - try stream.write("!"); - try renderExpression(allocator, stream, tree, indent, node); + try renderToken(tree, stream, tree.prevToken(node.firstToken()), indent, Space.None); // ! + try renderExpression(allocator, stream, tree, indent, node, space); }, } }, ast.Node.Id.PromiseType => { const promise_type = @fieldParentPtr(ast.Node.PromiseType, "base", base); - try stream.write(tree.tokenSlice(promise_type.promise_token)); + if (promise_type.result) |result| { - try stream.write(tree.tokenSlice(result.arrow_token)); - try renderExpression(allocator, stream, tree, indent, result.return_type); + try renderToken(tree, stream, promise_type.promise_token, indent, Space.None); // promise + try renderToken(tree, stream, result.arrow_token, indent, Space.None); // -> + try renderExpression(allocator, stream, tree, indent, result.return_type, space); + } else { + try renderToken(tree, stream, promise_type.promise_token, indent, space); // promise } }, - ast.Node.Id.LineComment => { - const line_comment_node = @fieldParentPtr(ast.Node.LineComment, "base", base); - try stream.write(tree.tokenSlice(line_comment_node.token)); - }, - ast.Node.Id.DocComment => unreachable, // doc comments are attached to nodes ast.Node.Id.Switch => { const switch_node = @fieldParentPtr(ast.Node.Switch, "base", base); - try stream.print("{} (", tree.tokenSlice(switch_node.switch_token)); + try renderToken(tree, stream, switch_node.switch_token, indent, Space.Space); // switch + try renderToken(tree, stream, tree.nextToken(switch_node.switch_token), indent, Space.None); // ( + + const rparen = tree.nextToken(switch_node.expr.lastToken()); + const lbrace = tree.nextToken(rparen); + if (switch_node.cases.len == 0) { - try renderExpression(allocator, stream, tree, indent, switch_node.expr); - try stream.write(") {}"); + try renderExpression(allocator, stream, tree, indent, switch_node.expr, Space.None); + try renderToken(tree, stream, rparen, indent, Space.Space); // ) + try renderToken(tree, stream, lbrace, indent, Space.None); // { + try renderToken(tree, stream, switch_node.rbrace, indent, space); // } return; } - try renderExpression(allocator, stream, tree, indent, switch_node.expr); - try stream.write(") {\n"); + try renderExpression(allocator, stream, tree, indent, switch_node.expr, Space.None); + + try renderToken(tree, stream, rparen, indent, Space.Space); // ) + try renderToken(tree, stream, lbrace, indent, Space.Newline); // { const new_indent = indent + indent_delta; var it = switch_node.cases.iterator(0); while (it.next()) |node| { try stream.writeByteNTimes(' ', new_indent); - try renderExpression(allocator, stream, tree, new_indent, node.*); + try renderExpression(allocator, stream, tree, new_indent, node.*, Space.Newline); if (it.peek()) |next_node| { - const n = if (nodeLineOffset(tree, node.*, next_node.*) >= 2) u8(2) else u8(1); - try stream.writeByteNTimes('\n', n); + try renderExtraNewline(tree, stream, next_node.*); } } - try stream.write("\n"); try stream.writeByteNTimes(' ', indent); - try stream.write("}"); + try renderToken(tree, stream, switch_node.rbrace, indent, space); // } }, ast.Node.Id.SwitchCase => { @@ -815,54 +890,50 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind var it = switch_case.items.iterator(0); while (it.next()) |node| { - try renderExpression(allocator, stream, tree, indent, node.*); + if (it.peek()) |next_node| { + try renderExpression(allocator, stream, tree, indent, node.*, Space.None); - if (it.peek() != null) { - try stream.write(",\n"); + const comma_token = tree.nextToken(node.*.lastToken()); + try renderToken(tree, stream, comma_token, indent, Space.Newline); // , + try renderExtraNewline(tree, stream, next_node.*); try stream.writeByteNTimes(' ', indent); + } else { + try renderExpression(allocator, stream, tree, indent, node.*, Space.Space); } } - try stream.write(" => "); + try renderToken(tree, stream, switch_case.arrow_token, indent, Space.Space); // => if (switch_case.payload) |payload| { - try renderExpression(allocator, stream, tree, indent, payload); - try stream.write(" "); + try renderExpression(allocator, stream, tree, indent, payload, Space.Space); } - try renderExpression(allocator, stream, tree, indent, switch_case.expr); - { - // Handle missing comma after last switch case - var index = switch_case.lastToken() + 1; - switch (tree.tokens.at(index).id) { - Token.Id.RBrace => { - try stream.write(","); - }, - Token.Id.LineComment => { - try stream.write(", "); - try renderToken(tree, stream, index, indent, true, true); - }, - else => try renderToken(tree, stream, index, indent, true, true), - } + // add a trailing comma if necessary + const end_token = switch_case.lastToken() + 1; + switch (tree.tokens.at(end_token).id) { + Token.Id.Comma => { + try renderExpression(allocator, stream, tree, indent, switch_case.expr, Space.None); + try renderToken(tree, stream, end_token, indent, space); // , + }, + Token.Id.LineComment => { + try renderExpression(allocator, stream, tree, indent, switch_case.expr, Space.NoComment); + try stream.write(", "); + try renderToken(tree, stream, end_token, indent, space); + }, + else => { + try renderExpression(allocator, stream, tree, indent, switch_case.expr, Space.None); + try stream.write(",\n"); + assert(space == Space.Newline); + }, } }, ast.Node.Id.SwitchElse => { const switch_else = @fieldParentPtr(ast.Node.SwitchElse, "base", base); - try stream.print("{}", tree.tokenSlice(switch_else.token)); + try renderToken(tree, stream, switch_else.token, indent, space); }, ast.Node.Id.Else => { const else_node = @fieldParentPtr(ast.Node.Else, "base", base); - var prev_tok_index = else_node.else_token - 1; - while (tree.tokens.at(prev_tok_index).id == Token.Id.LineComment) : (prev_tok_index -= 1) { } - prev_tok_index += 1; - while (prev_tok_index < else_node.else_token) : (prev_tok_index += 1) { - try stream.print("{}\n", tree.tokenSlice(prev_tok_index)); - try stream.writeByteNTimes(' ', indent); - } - - try stream.print("{}", tree.tokenSlice(else_node.else_token)); - const block_body = switch (else_node.body.id) { ast.Node.Id.Block, ast.Node.Id.If, @@ -872,21 +943,19 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind else => false, }; - if (block_body) { - try stream.write(" "); - } + const after_else_space = if (block_body or else_node.payload != null) Space.Space else Space.Newline; + try renderToken(tree, stream, else_node.else_token, indent, after_else_space); if (else_node.payload) |payload| { - try renderExpression(allocator, stream, tree, indent, payload); - try stream.write(" "); + const payload_space = if (block_body) Space.Space else Space.Newline; + try renderExpression(allocator, stream, tree, indent, payload, Space.Space); } if (block_body) { - try renderExpression(allocator, stream, tree, indent, else_node.body); + try renderExpression(allocator, stream, tree, indent, else_node.body, space); } else { - try stream.write("\n"); try stream.writeByteNTimes(' ', indent + indent_delta); - try renderExpression(allocator, stream, tree, indent, else_node.body); + try renderExpression(allocator, stream, tree, indent, else_node.body, space); } }, @@ -894,103 +963,134 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind const while_node = @fieldParentPtr(ast.Node.While, "base", base); if (while_node.label) |label| { - try stream.print("{}: ", tree.tokenSlice(label)); + try renderToken(tree, stream, label, indent, Space.None); // label + try renderToken(tree, stream, tree.nextToken(label), indent, Space.Space); // : } if (while_node.inline_token) |inline_token| { - try stream.print("{} ", tree.tokenSlice(inline_token)); + try renderToken(tree, stream, inline_token, indent, Space.Space); // inline } - try stream.print("{} (", tree.tokenSlice(while_node.while_token)); - try renderExpression(allocator, stream, tree, indent, while_node.condition); - try stream.write(")"); + try renderToken(tree, stream, while_node.while_token, indent, Space.Space); // while + try renderToken(tree, stream, tree.nextToken(while_node.while_token), indent, Space.None); // ( + try renderExpression(allocator, stream, tree, indent, while_node.condition, Space.None); + + { + const rparen = tree.nextToken(while_node.condition.lastToken()); + const rparen_space = if (while_node.payload != null or while_node.continue_expr != null or + while_node.body.id == ast.Node.Id.Block) Space.Space else Space.Newline; + try renderToken(tree, stream, rparen, indent, rparen_space); // ) + } if (while_node.payload) |payload| { - try stream.write(" "); - try renderExpression(allocator, stream, tree, indent, payload); + try renderExpression(allocator, stream, tree, indent, payload, Space.Space); } if (while_node.continue_expr) |continue_expr| { - try stream.write(" : ("); - try renderExpression(allocator, stream, tree, indent, continue_expr); - try stream.write(")"); + const rparen = tree.nextToken(continue_expr.lastToken()); + const lparen = tree.prevToken(continue_expr.firstToken()); + const colon = tree.prevToken(lparen); + + try renderToken(tree, stream, colon, indent, Space.Space); // : + try renderToken(tree, stream, lparen, indent, Space.None); // ( + + try renderExpression(allocator, stream, tree, indent, continue_expr, Space.None); + + const rparen_space = if (while_node.body.id == ast.Node.Id.Block) Space.Space else Space.Newline; + try renderToken(tree, stream, rparen, indent, rparen_space); // ) } + const body_space = blk: { + if (while_node.@"else" != null) { + break :blk if (while_node.body.id == ast.Node.Id.Block) Space.Space else Space.Newline; + } else { + break :blk space; + } + }; + if (while_node.body.id == ast.Node.Id.Block) { - try stream.write(" "); - try renderExpression(allocator, stream, tree, indent, while_node.body); + try renderExpression(allocator, stream, tree, indent, while_node.body, body_space); } else { - try stream.write("\n"); try stream.writeByteNTimes(' ', indent + indent_delta); - try renderExpression(allocator, stream, tree, indent, while_node.body); + try renderExpression(allocator, stream, tree, indent, while_node.body, body_space); } if (while_node.@"else") |@"else"| { if (while_node.body.id == ast.Node.Id.Block) { - try stream.write(" "); } else { - try stream.write("\n"); try stream.writeByteNTimes(' ', indent); } - try renderExpression(allocator, stream, tree, indent, &@"else".base); + try renderExpression(allocator, stream, tree, indent, &@"else".base, space); } }, ast.Node.Id.For => { const for_node = @fieldParentPtr(ast.Node.For, "base", base); + if (for_node.label) |label| { - try stream.print("{}: ", tree.tokenSlice(label)); + try renderToken(tree, stream, label, indent, Space.None); // label + try renderToken(tree, stream, tree.nextToken(label), indent, Space.Space); // : } if (for_node.inline_token) |inline_token| { - try stream.print("{} ", tree.tokenSlice(inline_token)); + try renderToken(tree, stream, inline_token, indent, Space.Space); // inline } - try stream.print("{} (", tree.tokenSlice(for_node.for_token)); - try renderExpression(allocator, stream, tree, indent, for_node.array_expr); - try stream.write(")"); + try renderToken(tree, stream, for_node.for_token, indent, Space.Space); // for + try renderToken(tree, stream, tree.nextToken(for_node.for_token), indent, Space.None); // ( + try renderExpression(allocator, stream, tree, indent, for_node.array_expr, Space.None); + + const rparen = tree.nextToken(for_node.array_expr.lastToken()); + const rparen_space = if (for_node.payload != null or + for_node.body.id == ast.Node.Id.Block) Space.Space else Space.Newline; + try renderToken(tree, stream, rparen, indent, rparen_space); // ) if (for_node.payload) |payload| { - try stream.write(" "); - try renderExpression(allocator, stream, tree, indent, payload); + const payload_space = if (for_node.body.id == ast.Node.Id.Block) Space.Space else Space.Newline; + try renderExpression(allocator, stream, tree, indent, payload, payload_space); } + const body_space = blk: { + if (for_node.@"else" != null) { + if (for_node.body.id == ast.Node.Id.Block) { + break :blk Space.Space; + } else { + break :blk Space.Newline; + } + } else { + break :blk space; + } + }; if (for_node.body.id == ast.Node.Id.Block) { - try stream.write(" "); - try renderExpression(allocator, stream, tree, indent, for_node.body); + try renderExpression(allocator, stream, tree, indent, for_node.body, body_space); } else { - try stream.write("\n"); try stream.writeByteNTimes(' ', indent + indent_delta); - try renderExpression(allocator, stream, tree, indent, for_node.body); + try renderExpression(allocator, stream, tree, indent, for_node.body, body_space); } if (for_node.@"else") |@"else"| { - if (for_node.body.id == ast.Node.Id.Block) { - try stream.write(" "); - } else { - try stream.write("\n"); + if (for_node.body.id != ast.Node.Id.Block) { try stream.writeByteNTimes(' ', indent); } - try renderExpression(allocator, stream, tree, indent, &@"else".base); + try renderExpression(allocator, stream, tree, indent, &@"else".base, space); } }, ast.Node.Id.If => { const if_node = @fieldParentPtr(ast.Node.If, "base", base); - try stream.print("{} (", tree.tokenSlice(if_node.if_token)); - try renderExpression(allocator, stream, tree, indent, if_node.condition); - try renderToken(tree, stream, if_node.condition.lastToken() + 1, indent, false, true); + try renderToken(tree, stream, if_node.if_token, indent, Space.Space); + try renderToken(tree, stream, tree.prevToken(if_node.condition.firstToken()), indent, Space.None); + + try renderExpression(allocator, stream, tree, indent, if_node.condition, Space.None); + try renderToken(tree, stream, tree.nextToken(if_node.condition.lastToken()), indent, Space.Space); if (if_node.payload) |payload| { - try renderExpression(allocator, stream, tree, indent, payload); - try stream.write(" "); + try renderExpression(allocator, stream, tree, indent, payload, Space.Space); } - try renderExpression(allocator, stream, tree, indent, if_node.body); - switch (if_node.body.id) { ast.Node.Id.Block, ast.Node.Id.If, @@ -999,25 +1099,29 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind ast.Node.Id.Switch => { if (if_node.@"else") |@"else"| { if (if_node.body.id == ast.Node.Id.Block) { - try stream.write(" "); + try renderExpression(allocator, stream, tree, indent, if_node.body, Space.Space); } else { - try stream.write("\n"); + try renderExpression(allocator, stream, tree, indent, if_node.body, Space.Newline); try stream.writeByteNTimes(' ', indent); } - try renderExpression(allocator, stream, tree, indent, &@"else".base); + try renderExpression(allocator, stream, tree, indent, &@"else".base, space); + } else { + try renderExpression(allocator, stream, tree, indent, if_node.body, space); } }, else => { if (if_node.@"else") |@"else"| { - try stream.print(" {} ", tree.tokenSlice(@"else".else_token)); + try renderExpression(allocator, stream, tree, indent, if_node.body, Space.Space); + try renderToken(tree, stream, @"else".else_token, indent, Space.Space); if (@"else".payload) |payload| { - try renderExpression(allocator, stream, tree, indent, payload); - try stream.write(" "); + try renderExpression(allocator, stream, tree, indent, payload, Space.Space); } - try renderExpression(allocator, stream, tree, indent, @"else".body); + try renderExpression(allocator, stream, tree, indent, @"else".body, space); + } else { + try renderExpression(allocator, stream, tree, indent, if_node.body, space); } }, } @@ -1025,15 +1129,17 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind ast.Node.Id.Asm => { const asm_node = @fieldParentPtr(ast.Node.Asm, "base", base); - try stream.print("{} ", tree.tokenSlice(asm_node.asm_token)); + + try renderToken(tree, stream, asm_node.asm_token, indent, Space.Space); // asm if (asm_node.volatile_token) |volatile_token| { - try stream.print("{} ", tree.tokenSlice(volatile_token)); + try renderToken(tree, stream, volatile_token, indent, Space.Space); // volatile + try renderToken(tree, stream, tree.nextToken(volatile_token), indent, Space.None); // ( + } else { + try renderToken(tree, stream, tree.nextToken(asm_node.asm_token), indent, Space.None); // ( } - try stream.print("("); - try renderExpression(allocator, stream, tree, indent, asm_node.template); - try stream.print("\n"); + try renderExpression(allocator, stream, tree, indent, asm_node.template, Space.Newline); const indent_once = indent + indent_delta; try stream.writeByteNTimes(' ', indent_once); try stream.print(": "); @@ -1043,13 +1149,15 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind var it = asm_node.outputs.iterator(0); while (it.next()) |asm_output| { const node = &(asm_output.*).base; - try renderExpression(allocator, stream, tree, indent_extra, node); + try renderExpression(allocator, stream, tree, indent_extra, node, Space.None); if (it.peek()) |next_asm_output| { const next_node = &(next_asm_output.*).base; - const n = if (nodeLineOffset(tree, node, next_node) >= 2) u8(2) else u8(1); - try stream.writeByte(','); - try stream.writeByteNTimes('\n', n); + + const comma = tree.prevToken(next_asm_output.*.firstToken()); + try renderToken(tree, stream, comma, indent_extra, Space.Newline); // , + try renderExtraNewline(tree, stream, next_node); + try stream.writeByteNTimes(' ', indent_extra); } } @@ -1063,13 +1171,15 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind var it = asm_node.inputs.iterator(0); while (it.next()) |asm_input| { const node = &(asm_input.*).base; - try renderExpression(allocator, stream, tree, indent_extra, node); + try renderExpression(allocator, stream, tree, indent_extra, node, Space.None); if (it.peek()) |next_asm_input| { const next_node = &(next_asm_input.*).base; - const n = if (nodeLineOffset(tree, node, next_node) >= 2) u8(2) else u8(1); - try stream.writeByte(','); - try stream.writeByteNTimes('\n', n); + + const comma = tree.prevToken(next_asm_input.*.firstToken()); + try renderToken(tree, stream, comma, indent_extra, Space.Newline); // , + try renderExtraNewline(tree, stream, next_node); + try stream.writeByteNTimes(' ', indent_extra); } } @@ -1082,7 +1192,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind { var it = asm_node.clobbers.iterator(0); while (it.next()) |node| { - try renderExpression(allocator, stream, tree, indent_once, node.*); + try renderExpression(allocator, stream, tree, indent_once, node.*, Space.None); if (it.peek() != null) { try stream.write(", "); @@ -1090,47 +1200,46 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind } } - try stream.write(")"); + try renderToken(tree, stream, asm_node.rparen, indent, space); }, ast.Node.Id.AsmInput => { const asm_input = @fieldParentPtr(ast.Node.AsmInput, "base", base); try stream.write("["); - try renderExpression(allocator, stream, tree, indent, asm_input.symbolic_name); + try renderExpression(allocator, stream, tree, indent, asm_input.symbolic_name, Space.None); try stream.write("] "); - try renderExpression(allocator, stream, tree, indent, asm_input.constraint); + try renderExpression(allocator, stream, tree, indent, asm_input.constraint, Space.None); try stream.write(" ("); - try renderExpression(allocator, stream, tree, indent, asm_input.expr); - try stream.write(")"); + try renderExpression(allocator, stream, tree, indent, asm_input.expr, Space.None); + try renderToken(tree, stream, asm_input.lastToken(), indent, space); // ) }, ast.Node.Id.AsmOutput => { const asm_output = @fieldParentPtr(ast.Node.AsmOutput, "base", base); try stream.write("["); - try renderExpression(allocator, stream, tree, indent, asm_output.symbolic_name); + try renderExpression(allocator, stream, tree, indent, asm_output.symbolic_name, Space.None); try stream.write("] "); - try renderExpression(allocator, stream, tree, indent, asm_output.constraint); + try renderExpression(allocator, stream, tree, indent, asm_output.constraint, Space.None); try stream.write(" ("); switch (asm_output.kind) { ast.Node.AsmOutput.Kind.Variable => |variable_name| { - try renderExpression(allocator, stream, tree, indent, &variable_name.base); + try renderExpression(allocator, stream, tree, indent, &variable_name.base, Space.None); }, ast.Node.AsmOutput.Kind.Return => |return_type| { try stream.write("-> "); - try renderExpression(allocator, stream, tree, indent, return_type); + try renderExpression(allocator, stream, tree, indent, return_type, Space.None); }, } - try stream.write(")"); + try renderToken(tree, stream, asm_output.lastToken(), indent, space); // ) }, ast.Node.Id.StructField, ast.Node.Id.UnionTag, ast.Node.Id.EnumTag, - ast.Node.Id.ErrorTag, ast.Node.Id.Root, ast.Node.Id.VarDecl, ast.Node.Id.Use, @@ -1139,70 +1248,74 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind } } -fn renderVarDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent: usize, var_decl: &ast.Node.VarDecl) (@typeOf(stream).Child.Error || Error)!void { +fn renderVarDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent: usize, + var_decl: &ast.Node.VarDecl) (@typeOf(stream).Child.Error || Error)!void +{ if (var_decl.visib_token) |visib_token| { - try renderToken(tree, stream, visib_token, indent, false, true); + try renderToken(tree, stream, visib_token, indent, Space.Space); // pub } if (var_decl.extern_export_token) |extern_export_token| { - try renderToken(tree, stream, extern_export_token, indent, false, true); + try renderToken(tree, stream, extern_export_token, indent, Space.Space); // extern if (var_decl.lib_name) |lib_name| { - try renderExpression(allocator, stream, tree, indent, lib_name); - try stream.write(" "); + try renderExpression(allocator, stream, tree, indent, lib_name, Space.Space); // "lib" } } if (var_decl.comptime_token) |comptime_token| { - try renderToken(tree, stream, comptime_token, indent, false, true); + try renderToken(tree, stream, comptime_token, indent, Space.Space); // comptime } - try renderToken(tree, stream, var_decl.mut_token, indent, false, true); - try renderToken(tree, stream, var_decl.name_token, indent, false, false); + try renderToken(tree, stream, var_decl.mut_token, indent, Space.Space); // var + + const name_space = if (var_decl.type_node == null and (var_decl.align_node != null or + var_decl.init_node != null)) Space.Space else Space.None; + try renderToken(tree, stream, var_decl.name_token, indent, name_space); if (var_decl.type_node) |type_node| { - try stream.write(": "); - try renderExpression(allocator, stream, tree, indent, type_node); + try renderToken(tree, stream, tree.nextToken(var_decl.name_token), indent, Space.Space); + const s = if (var_decl.align_node != null or var_decl.init_node != null) Space.Space else Space.None; + try renderExpression(allocator, stream, tree, indent, type_node, s); } if (var_decl.align_node) |align_node| { - try stream.write(" align("); - try renderExpression(allocator, stream, tree, indent, align_node); - try stream.write(")"); + const lparen = tree.prevToken(align_node.firstToken()); + const align_kw = tree.prevToken(lparen); + const rparen = tree.nextToken(align_node.lastToken()); + try renderToken(tree, stream, align_kw, indent, Space.None); // align + try renderToken(tree, stream, lparen, indent, Space.None); // ( + try renderExpression(allocator, stream, tree, indent, align_node, Space.None); + const s = if (var_decl.init_node != null) Space.Space else Space.None; + try renderToken(tree, stream, rparen, indent, s); // ) } if (var_decl.init_node) |init_node| { - const text = if (init_node.id == ast.Node.Id.MultilineStringLiteral) " =" else " = "; - try stream.write(text); - try renderExpression(allocator, stream, tree, indent, init_node); + const s = if (init_node.id == ast.Node.Id.MultilineStringLiteral) Space.None else Space.Space; + try renderToken(tree, stream, var_decl.eq_token, indent, s); // = + try renderExpression(allocator, stream, tree, indent, init_node, Space.None); } - try renderToken(tree, stream, var_decl.semicolon_token, indent, true, false); -} - -fn maybeRenderSemicolon(stream: var, tree: &ast.Tree, indent: usize, base: &ast.Node) (@typeOf(stream).Child.Error || Error)!void { - if (base.requireSemiColon()) { - const semicolon_index = base.lastToken() + 1; - assert(tree.tokens.at(semicolon_index).id == Token.Id.Semicolon); - try renderToken(tree, stream, semicolon_index, indent, true, true); - } + try renderToken(tree, stream, var_decl.semicolon_token, indent, Space.Newline); } fn renderParamDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent: usize, base: &ast.Node) (@typeOf(stream).Child.Error || Error)!void { const param_decl = @fieldParentPtr(ast.Node.ParamDecl, "base", base); + if (param_decl.comptime_token) |comptime_token| { - try stream.print("{} ", tree.tokenSlice(comptime_token)); + try renderToken(tree, stream, comptime_token, indent, Space.Space); } if (param_decl.noalias_token) |noalias_token| { - try stream.print("{} ", tree.tokenSlice(noalias_token)); + try renderToken(tree, stream, noalias_token, indent, Space.Space); } if (param_decl.name_token) |name_token| { - try stream.print("{}: ", tree.tokenSlice(name_token)); + try renderToken(tree, stream, name_token, indent, Space.None); + try renderToken(tree, stream, tree.nextToken(name_token), indent, Space.Space); // : } if (param_decl.var_args_token) |var_args_token| { - try stream.print("{}", tree.tokenSlice(var_args_token)); + try renderToken(tree, stream, var_args_token, indent, Space.None); } else { - try renderExpression(allocator, stream, tree, indent, param_decl.type_node); + try renderExpression(allocator, stream, tree, indent, param_decl.type_node, Space.None); } } @@ -1213,41 +1326,104 @@ fn renderStatement(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, inde try renderVarDecl(allocator, stream, tree, indent, var_decl); }, else => { - try renderExpression(allocator, stream, tree, indent, base); - try maybeRenderSemicolon(stream, tree, indent, base); + if (base.requireSemiColon()) { + try renderExpression(allocator, stream, tree, indent, base, Space.None); + + const semicolon_index = tree.nextToken(base.lastToken()); + assert(tree.tokens.at(semicolon_index).id == Token.Id.Semicolon); + try renderToken(tree, stream, semicolon_index, indent, Space.Newline); + } else { + try renderExpression(allocator, stream, tree, indent, base, Space.Newline); + } }, } } -fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent: usize, line_break: bool, space: bool) (@typeOf(stream).Child.Error || Error)!void { - const token = tree.tokens.at(token_index); +const Space = enum { + None, + Newline, + Space, + NoNewline, + NoIndent, + NoComment, +}; + +fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent: usize, space: Space) (@typeOf(stream).Child.Error || Error)!void { + var token = tree.tokens.at(token_index); try stream.write(tree.tokenSlicePtr(token)); - const next_token = tree.tokens.at(token_index + 1); - if (next_token.id == Token.Id.LineComment) { - const loc = tree.tokenLocationPtr(token.end, next_token); - if (loc.line == 0) { - try stream.print(" {}", tree.tokenSlicePtr(next_token)); - if (!line_break) { - try stream.write("\n"); + if (space == Space.NoComment) return; - const after_comment_token = tree.tokens.at(token_index + 2); - const next_line_indent = switch (after_comment_token.id) { - Token.Id.RParen, Token.Id.RBrace, Token.Id.RBracket => indent, - else => indent + indent_delta, - }; - try stream.writeByteNTimes(' ', next_line_indent); - return; + var next_token = tree.tokens.at(token_index + 1); + if (next_token.id != Token.Id.LineComment) { + switch (space) { + Space.None, Space.NoNewline, Space.NoIndent => return, + Space.Newline => return stream.write("\n"), + Space.Space => return stream.writeByte(' '), + Space.NoComment => unreachable, + } + } + + var loc = tree.tokenLocationPtr(token.end, next_token); + var offset: usize = 1; + if (loc.line == 0) { + try stream.print(" {}", tree.tokenSlicePtr(next_token)); + offset = 2; + token = next_token; + next_token = tree.tokens.at(token_index + offset); + if (next_token.id != Token.Id.LineComment) { + switch (space) { + Space.None, Space.Space => { + try stream.writeByte('\n'); + const after_comment_token = tree.tokens.at(token_index + offset); + const next_line_indent = switch (after_comment_token.id) { + Token.Id.RParen, Token.Id.RBrace, Token.Id.RBracket => indent, + else => indent + indent_delta, + }; + try stream.writeByteNTimes(' ', next_line_indent); + }, + Space.Newline, Space.NoIndent => try stream.write("\n"), + Space.NoNewline => {}, + Space.NoComment => unreachable, } + return; } + loc = tree.tokenLocationPtr(token.end, next_token); } - if (!line_break and space) { - try stream.writeByte(' '); + while (true) { + assert(loc.line != 0); + const newline_count = if (loc.line == 1) u8(1) else u8(2); + try stream.writeByteNTimes('\n', newline_count); + try stream.writeByteNTimes(' ', indent); + try stream.write(tree.tokenSlicePtr(next_token)); + + offset += 1; + token = next_token; + next_token = tree.tokens.at(token_index + offset); + if (next_token.id != Token.Id.LineComment) { + switch (space) { + Space.Newline, Space.NoIndent => try stream.writeByte('\n'), + Space.None, Space.Space => { + try stream.writeByte('\n'); + + const after_comment_token = tree.tokens.at(token_index + offset); + const next_line_indent = switch (after_comment_token.id) { + Token.Id.RParen, Token.Id.RBrace, Token.Id.RBracket => indent, + else => indent, + }; + try stream.writeByteNTimes(' ', next_line_indent); + }, + Space.NoNewline => {}, + Space.NoComment => unreachable, + } + return; + } + loc = tree.tokenLocationPtr(token.end, next_token); } } -fn renderComments(tree: &ast.Tree, stream: var, node: var, indent: usize) (@typeOf(stream).Child.Error || Error)!void { +fn renderDocComments(tree: &ast.Tree, stream: var, node: var, indent: usize) (@typeOf(stream).Child.Error || Error)!void { const comment = node.doc_comments ?? return; var it = comment.lines.iterator(0); while (it.next()) |line_token_index| { -- 2.54.0 From 54e887ed9e774c6fd68f51d97e2c5c760e48be30 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 24 May 2018 01:15:50 -0400 Subject: [PATCH 33/47] std.zig.tokenizer: fix tokenization of hex floats --- std/zig/parser_test.zig | 15 +++++---- std/zig/tokenizer.zig | 75 +++++++++++++++++++++++++++++++++++++---- 2 files changed, 77 insertions(+), 13 deletions(-) diff --git a/std/zig/parser_test.zig b/std/zig/parser_test.zig index 38ffee8aaf32412ab7996c3a1f082e4f9ffed788..c11db787757eadc3dbe24f06c7875f1a367dad40 100644 --- a/std/zig/parser_test.zig +++ b/std/zig/parser_test.zig @@ -1,3 +1,11 @@ +test "zig fmt: float literal with exponent" { + try testCanonical( + \\pub const f64_true_min = 4.94065645841246544177e-324; + \\const threshold = 0x1.a827999fcef32p+1022; + \\ + ); +} + test "zig fmt: if-else end of comptime" { try testCanonical( \\comptime { @@ -238,13 +246,6 @@ test "zig fmt: switch with empty body" { ); } -test "zig fmt: float literal with exponent" { - try testCanonical( - \\pub const f64_true_min = 4.94065645841246544177e-324; - \\ - ); -} - test "zig fmt: line comments in struct initializer" { try testCanonical( \\fn foo() void { diff --git a/std/zig/tokenizer.zig b/std/zig/tokenizer.zig index b0e5014a1aae438fed315ba0d3003a9b9d87670c..afea7fc899d637a0c95099b933fbf988a951f324 100644 --- a/std/zig/tokenizer.zig +++ b/std/zig/tokenizer.zig @@ -6,12 +6,12 @@ pub const Token = struct { start: usize, end: usize, - const Keyword = struct { + pub const Keyword = struct { bytes: []const u8, id: Id, }; - const keywords = []Keyword { + pub const keywords = []Keyword { Keyword{.bytes="align", .id = Id.Keyword_align}, Keyword{.bytes="and", .id = Id.Keyword_and}, Keyword{.bytes="asm", .id = Id.Keyword_asm}, @@ -62,6 +62,7 @@ pub const Token = struct { Keyword{.bytes="while", .id = Id.Keyword_while}, }; + // TODO perfect hash at comptime fn getKeyword(bytes: []const u8) ?Id { for (keywords) |kw| { if (mem.eql(u8, kw.bytes, bytes)) { @@ -236,10 +237,15 @@ pub const Tokenizer = struct { Zero, IntegerLiteral, IntegerLiteralWithRadix, + IntegerLiteralWithRadixHex, NumberDot, + NumberDotHex, FloatFraction, + FloatFractionHex, FloatExponentUnsigned, + FloatExponentUnsignedHex, FloatExponentNumber, + FloatExponentNumberHex, Ampersand, Caret, Percent, @@ -839,9 +845,12 @@ pub const Tokenizer = struct { else => self.checkLiteralCharacter(), }, State.Zero => switch (c) { - 'b', 'o', 'x' => { + 'b', 'o' => { state = State.IntegerLiteralWithRadix; }, + 'x' => { + state = State.IntegerLiteralWithRadixHex; + }, else => { // reinterpret as a normal number self.index -= 1; @@ -862,8 +871,15 @@ pub const Tokenizer = struct { '.' => { state = State.NumberDot; }, + '0'...'9' => {}, + else => break, + }, + State.IntegerLiteralWithRadixHex => switch (c) { + '.' => { + state = State.NumberDotHex; + }, 'p', 'P' => { - state = State.FloatExponentUnsigned; + state = State.FloatExponentUnsignedHex; }, '0'...'9', 'a'...'f', 'A'...'F' => {}, else => break, @@ -880,13 +896,32 @@ pub const Tokenizer = struct { state = State.FloatFraction; }, }, + State.NumberDotHex => switch (c) { + '.' => { + self.index -= 1; + state = State.Start; + break; + }, + else => { + self.index -= 1; + result.id = Token.Id.FloatLiteral; + state = State.FloatFractionHex; + }, + }, State.FloatFraction => switch (c) { - 'p', 'P', 'e', 'E' => { + 'e', 'E' => { state = State.FloatExponentUnsigned; }, '0'...'9' => {}, else => break, }, + State.FloatFractionHex => switch (c) { + 'p', 'P' => { + state = State.FloatExponentUnsignedHex; + }, + '0'...'9', 'a'...'f', 'A'...'F' => {}, + else => break, + }, State.FloatExponentUnsigned => switch (c) { '+', '-' => { state = State.FloatExponentNumber; @@ -897,7 +932,21 @@ pub const Tokenizer = struct { state = State.FloatExponentNumber; } }, + State.FloatExponentUnsignedHex => switch (c) { + '+', '-' => { + state = State.FloatExponentNumberHex; + }, + else => { + // reinterpret as a normal exponent number + self.index -= 1; + state = State.FloatExponentNumberHex; + } + }, State.FloatExponentNumber => switch (c) { + '0'...'9' => {}, + else => break, + }, + State.FloatExponentNumberHex => switch (c) { '0'...'9', 'a'...'f', 'A'...'F' => {}, else => break, }, @@ -908,8 +957,11 @@ pub const Tokenizer = struct { State.C, State.IntegerLiteral, State.IntegerLiteralWithRadix, + State.IntegerLiteralWithRadixHex, State.FloatFraction, + State.FloatFractionHex, State.FloatExponentNumber, + State.FloatExponentNumberHex, State.StringLiteral, // find this error later State.MultilineStringLiteralLine, State.Builtin => {}, @@ -928,7 +980,9 @@ pub const Tokenizer = struct { }, State.NumberDot, + State.NumberDotHex, State.FloatExponentUnsigned, + State.FloatExponentUnsignedHex, State.SawAtSign, State.Backslash, State.MultilineStringLiteralLineBackslash, @@ -1073,7 +1127,7 @@ test "tokenizer" { }); } -test "tokenizer - float literal" { +test "tokenizer - float literal e exponent" { testTokenize("a = 4.94065645841246544177e-324;\n", []Token.Id { Token.Id.Identifier, Token.Id.Equal, @@ -1082,6 +1136,15 @@ test "tokenizer - float literal" { }); } +test "tokenizer - float literal p exponent" { + testTokenize("a = 0x1.a827999fcef32p+1022;\n", []Token.Id { + Token.Id.Identifier, + Token.Id.Equal, + Token.Id.FloatLiteral, + Token.Id.Semicolon, + }); +} + test "tokenizer - chars" { testTokenize("'c'", []Token.Id {Token.Id.CharLiteral}); } -- 2.54.0 From 938d791b23d58abf2bad4aa90ae3496ae9bb2435 Mon Sep 17 00:00:00 2001 From: "braedonww@gmail.com" Date: Thu, 17 May 2018 10:43:59 +1000 Subject: [PATCH 34/47] Added argtype and error inferring info --- doc/langref.html.in | 42 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/doc/langref.html.in b/doc/langref.html.in index d047c7d9f21344591ebc265c2f86b015e3a3642d..6995cbab337dedef84fb6adbc4ff058e9e178fa1 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -3111,7 +3111,40 @@ test "error union" { {#code_end#}

    TODO the || operator for error sets

    {#header_open|Inferred Error Sets#} -

    TODO

    +{#code_begin|syntax#} +// Defining error set +const NumberError = error { + Zero, + Negative, +}; + +// While you could define it like this explicitly saying the error domain. +// Which means you can return an error like `error.InvalidX` as it is not +// within the NumberError error enum. +fn positiveAdd(a: i32, b: i32) NumberError!i32 { + if (a == 0 or b == 0) return NumberError.Zero; + if (a < 0 or b < 0) return NumberError.Negative; + return a + b; +} + +// You could also just infer the error set from the given thrown errors +fn inferAdd(a: i32, b: i32) !i32 { + // Note: you could either do NumberError.Zero here or just error.Zero + if (a == 0 or b == 0) return error.Zero; + if (a < 0 or b < 0) return error.Negative; + return a + b; +} + +// Quick note: inferAdd creates a definition that has a return type that is; +const InferAddErrorSet = error { + Zero, + Negative, +}; +// Which since it contains only errors from NumberError it can be passed to functions like; +fn printNumberError(err: NumberError) void { } +// However if it also returned an error outside NumberError it would produce a compile error +// if passed into the above function. +{#code_end#} {#header_close#} {#header_close#} {#header_open|Error Return Traces#} @@ -3878,7 +3911,12 @@ pub fn main() void {

    {#header_close#} {#header_open|@ArgType#} -

    TODO

    +
    @ArgType(comptime T: type, comptime n: usize) -> type
    +

    + This builtin function takes a function type and returns the type of the 'n'th parameter. +

    +

    + T must be a function type, and n must be an usize integer. {#header_close#} {#header_open|@atomicLoad#}

    @atomicLoad(comptime T: type, ptr: &const T, comptime ordering: builtin.AtomicOrder) -> T
    -- 2.54.0 From fa5b0ef54fe7a612754c796a899020c73d5fb191 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 24 May 2018 20:59:19 -0400 Subject: [PATCH 35/47] doc fixups --- doc/langref.html.in | 72 ++++++++++++++++++++++++++------------------- 1 file changed, 42 insertions(+), 30 deletions(-) diff --git a/doc/langref.html.in b/doc/langref.html.in index 6995cbab337dedef84fb6adbc4ff058e9e178fa1..c3c50b117bc607b02d8b346098e98ccb6ac97a63 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -3111,40 +3111,48 @@ test "error union" { {#code_end#}

    TODO the || operator for error sets

    {#header_open|Inferred Error Sets#} -{#code_begin|syntax#} -// Defining error set -const NumberError = error { - Zero, - Negative, -}; - -// While you could define it like this explicitly saying the error domain. -// Which means you can return an error like `error.InvalidX` as it is not -// within the NumberError error enum. -fn positiveAdd(a: i32, b: i32) NumberError!i32 { - if (a == 0 or b == 0) return NumberError.Zero; - if (a < 0 or b < 0) return NumberError.Negative; - return a + b; +

    + Because many functions in Zig return a possible error, Zig supports inferring the error set. + To infer the error set for a function, use this syntax: +

    +{#code_begin|test#} +// With an inferred error set +pub fn add_inferred(comptime T: type, a: T, b: T) !T { + var answer: T = undefined; + return if (@addWithOverflow(T, a, b, &answer)) error.Overflow else answer; } -// You could also just infer the error set from the given thrown errors -fn inferAdd(a: i32, b: i32) !i32 { - // Note: you could either do NumberError.Zero here or just error.Zero - if (a == 0 or b == 0) return error.Zero; - if (a < 0 or b < 0) return error.Negative; - return a + b; +// With an explicit error set +pub fn add_explicit(comptime T: type, a: T, b: T) Error!T { + var answer: T = undefined; + return if (@addWithOverflow(T, a, b, &answer)) error.Overflow else answer; } -// Quick note: inferAdd creates a definition that has a return type that is; -const InferAddErrorSet = error { - Zero, - Negative, +const Error = error { + Overflow, }; -// Which since it contains only errors from NumberError it can be passed to functions like; -fn printNumberError(err: NumberError) void { } -// However if it also returned an error outside NumberError it would produce a compile error -// if passed into the above function. + +const std = @import("std"); + +test "inferred error set" { + if (add_inferred(u8, 255, 1)) |_| unreachable else |err| switch (err) { + error.Overflow => {}, // ok + } +} {#code_end#} +

    + When a function has an inferred error set, that function becomes generic and thus it becomes + trickier to do certain things with it, such as obtain a function pointer, or have an error + set that is consistent across different build targets. Additionally, inferred error sets + are incompatible with recursion. +

    +

    + In these situations, it is recommended to use an explicit error set. You can generally start + with an empty error set and let compile errors guide you toward completing the set. +

    +

    + These limitations may be overcome in a future version of Zig. +

    {#header_close#} {#header_close#} {#header_open|Error Return Traces#} @@ -3913,10 +3921,14 @@ pub fn main() void { {#header_open|@ArgType#}
    @ArgType(comptime T: type, comptime n: usize) -> type

    - This builtin function takes a function type and returns the type of the 'n'th parameter. + This builtin function takes a function type and returns the type of the parameter at index n.

    - T must be a function type, and n must be an usize integer. + T must be a function type. +

    +

    + Note: This function is deprecated. Use {#link|@typeInfo#} instead. +

    {#header_close#} {#header_open|@atomicLoad#}
    @atomicLoad(comptime T: type, ptr: &const T, comptime ordering: builtin.AtomicOrder) -> T
    -- 2.54.0 From 43085417bec447ab31f3454e180213f102885cc8 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 24 May 2018 21:27:44 -0400 Subject: [PATCH 36/47] update github.com/zig-lang to github.com/ziglang --- README.md | 4 ++-- doc/langref.html.in | 8 ++++---- example/hello_world/hello_libc.zig | 2 +- src/analyze.cpp | 4 ++-- src/codegen.cpp | 6 +++--- src/ir.cpp | 8 ++++---- std/atomic/queue.zig | 2 +- std/event.zig | 8 ++++---- std/fmt/index.zig | 2 +- std/mem.zig | 2 +- std/os/index.zig | 6 +++--- std/os/test.zig | 2 +- std/os/time.zig | 2 +- std/special/compiler_rt/comparetf2.zig | 4 ++-- std/zig/ast.zig | 4 ++-- test/build_examples.zig | 2 +- test/cases/coroutines.zig | 2 +- test/cases/misc.zig | 2 +- test/compare_output.zig | 4 ++-- 19 files changed, 37 insertions(+), 37 deletions(-) diff --git a/README.md b/README.md index cf4d8179c7528edd04987a22faceb9ce02cf488e..b5bf13f0958104caba78ebef1879f2804a60a4a5 100644 --- a/README.md +++ b/README.md @@ -114,7 +114,7 @@ libc. Create demo games using Zig. ## Building -[![Build Status](https://travis-ci.org/zig-lang/zig.svg?branch=master)](https://travis-ci.org/zig-lang/zig) +[![Build Status](https://travis-ci.org/ziglang/zig.svg?branch=master)](https://travis-ci.org/ziglang/zig) [![Build status](https://ci.appveyor.com/api/projects/status/4t80mk2dmucrc38i/branch/master?svg=true)](https://ci.appveyor.com/project/andrewrk/zig-d3l86/branch/master) ### Stage 1: Build Zig from C++ Source Code @@ -161,7 +161,7 @@ bin/zig build --build-file ../build.zig test ##### Windows -See https://github.com/zig-lang/zig/wiki/Building-Zig-on-Windows +See https://github.com/ziglang/zig/wiki/Building-Zig-on-Windows ### Stage 2: Build Self-Hosted Zig from Zig Source Code diff --git a/doc/langref.html.in b/doc/langref.html.in index c3c50b117bc607b02d8b346098e98ccb6ac97a63..d63c38d0fee658d85cba64a6b544c65d43aee58b 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -96,7 +96,7 @@

    If you search for something specific in this documentation and do not find it, - please file an issue or say something on IRC. + please file an issue or say something on IRC.

    The code samples in this document are compiled and tested as part of the main test suite of Zig. @@ -2827,7 +2827,7 @@ test "fn reflection" {

    The number of unique error values across the entire compilation should determine the size of the error set type. - However right now it is hard coded to be a u16. See #768. + However right now it is hard coded to be a u16. See #768.

    You can implicitly cast an error from a subset to its superset: @@ -5958,7 +5958,7 @@ pub fn main() void { {#code_begin|exe#} {#link_libc#} const c = @cImport({ - // See https://github.com/zig-lang/zig/issues/515 + // See https://github.com/ziglang/zig/issues/515 @cDefine("_NO_CRT_STDIO_INLINE", "1"); @cInclude("stdio.h"); }); @@ -6301,7 +6301,7 @@ fn readU32Be() u32 {}

  • Non-Ascii Unicode line endings: U+0085 (NEL), U+2028 (LS), U+2029 (PS).

The codepoint U+000a (LF) (which is encoded as the single-byte value 0x0a) is the line terminator character. This character always terminates a line of zig source code (except possbly the last line of the file).

-

For some discussion on the rationale behind these design decisions, see issue #663

+

For some discussion on the rationale behind these design decisions, see issue #663

{#header_close#} {#header_open|Grammar#}
Root = many(TopLevelItem) EOF
diff --git a/example/hello_world/hello_libc.zig b/example/hello_world/hello_libc.zig
index 60123c6fd82e230c058e3e0929466d8049dfe808..4a35e47b157b9cd0487f9759ed2cbab6f9754051 100644
--- a/example/hello_world/hello_libc.zig
+++ b/example/hello_world/hello_libc.zig
@@ -1,5 +1,5 @@
 const c = @cImport({
-    // See https://github.com/zig-lang/zig/issues/515
+    // See https://github.com/ziglang/zig/issues/515
     @cDefine("_NO_CRT_STDIO_INLINE", "1");
     @cInclude("stdio.h");
     @cInclude("string.h");
diff --git a/src/analyze.cpp b/src/analyze.cpp
index d6137a4286d003df231320905eb658b348d952e6..c59fde8ef687750540bc7a99c763ed6be904ee4b 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -1007,7 +1007,7 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
     if (fn_type_id->return_type != nullptr) {
         ensure_complete_type(g, fn_type_id->return_type);
     } else {
-        zig_panic("TODO implement inferred return types https://github.com/zig-lang/zig/issues/447");
+        zig_panic("TODO implement inferred return types https://github.com/ziglang/zig/issues/447");
     }
 
     TypeTableEntry *fn_type = new_type_table_entry(TypeTableEntryIdFn);
@@ -1556,7 +1556,7 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c
             return g->builtin_types.entry_invalid;
         }
         add_node_error(g, proto_node,
-            buf_sprintf("TODO implement inferred return types https://github.com/zig-lang/zig/issues/447"));
+            buf_sprintf("TODO implement inferred return types https://github.com/ziglang/zig/issues/447"));
         return g->builtin_types.entry_invalid;
         //return get_generic_fn_type(g, &fn_type_id);
     }
diff --git a/src/codegen.cpp b/src/codegen.cpp
index f1e102392a23f72e2efe71b38ce0afd19d8a8119..69542b3e675e7c0c0c88322885c43f8955864994 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -582,7 +582,7 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) {
             addLLVMArgAttr(fn_table_entry->llvm_value, (unsigned)gen_index, "nonnull");
         }
         // Note: byval is disabled on windows due to an LLVM bug:
-        // https://github.com/zig-lang/zig/issues/536
+        // https://github.com/ziglang/zig/issues/536
         if (is_byval && g->zig_target.os != OsWindows) {
             addLLVMArgAttr(fn_table_entry->llvm_value, (unsigned)gen_index, "byval");
         }
@@ -3067,7 +3067,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
     for (size_t param_i = 0; param_i < fn_type_id->param_count; param_i += 1) {
         FnGenParamInfo *gen_info = &fn_type->data.fn.gen_param_info[param_i];
         // Note: byval is disabled on windows due to an LLVM bug:
-        // https://github.com/zig-lang/zig/issues/536
+        // https://github.com/ziglang/zig/issues/536
         if (gen_info->is_byval && g->zig_target.os != OsWindows) {
             addLLVMCallsiteAttr(result, (unsigned)gen_info->gen_index, "byval");
         }
@@ -6730,7 +6730,7 @@ static void init(CodeGen *g) {
     const char *target_specific_features;
     if (g->is_native_target) {
         // LLVM creates invalid binaries on Windows sometimes.
-        // See https://github.com/zig-lang/zig/issues/508
+        // See https://github.com/ziglang/zig/issues/508
         // As a workaround we do not use target native features on Windows.
         if (g->zig_target.os == OsWindows) {
             target_specific_cpu_args = "";
diff --git a/src/ir.cpp b/src/ir.cpp
index e2cbba48a7acbcaa971e55a5b6becaa0e129c973..440063d58d7fde8f93e805f7f658d107a38a6cce 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -12130,7 +12130,7 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod
             casted_arg->value.type->id == TypeTableEntryIdNumLitFloat)
     {
         ir_add_error(ira, casted_arg,
-            buf_sprintf("compiler bug: integer and float literals in var args function must be casted. https://github.com/zig-lang/zig/issues/557"));
+            buf_sprintf("compiler bug: integer and float literals in var args function must be casted. https://github.com/ziglang/zig/issues/557"));
         return false;
     }
 
@@ -12331,7 +12331,7 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal
 
         if (fn_proto_node->data.fn_proto.is_var_args) {
             ir_add_error(ira, &call_instruction->base,
-                    buf_sprintf("compiler bug: unable to call var args function at compile time. https://github.com/zig-lang/zig/issues/313"));
+                    buf_sprintf("compiler bug: unable to call var args function at compile time. https://github.com/ziglang/zig/issues/313"));
             return ira->codegen->builtin_types.entry_invalid;
         }
 
@@ -12424,7 +12424,7 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal
         }
         if (call_instruction->is_async && fn_type_id->is_var_args) {
             ir_add_error(ira, call_instruction->fn_ref,
-                buf_sprintf("compiler bug: TODO: implement var args async functions. https://github.com/zig-lang/zig/issues/557"));
+                buf_sprintf("compiler bug: TODO: implement var args async functions. https://github.com/ziglang/zig/issues/557"));
             return ira->codegen->builtin_types.entry_invalid;
         }
 
@@ -12507,7 +12507,7 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal
                     VariableTableEntry *arg_var = get_fn_var_by_index(parent_fn_entry, arg_tuple_i);
                     if (arg_var == nullptr) {
                         ir_add_error(ira, arg,
-                            buf_sprintf("compiler bug: var args can't handle void. https://github.com/zig-lang/zig/issues/557"));
+                            buf_sprintf("compiler bug: var args can't handle void. https://github.com/ziglang/zig/issues/557"));
                         return ira->codegen->builtin_types.entry_invalid;
                     }
                     IrInstruction *arg_var_ptr_inst = ir_get_var_ptr(ira, arg, arg_var, true, false);
diff --git a/std/atomic/queue.zig b/std/atomic/queue.zig
index 288a2b3b48e8e3e8ce3af56a46bc79277f3dfa8c..35180da8d1ff53d3fb828b5cf4e9f3adfdc48072 100644
--- a/std/atomic/queue.zig
+++ b/std/atomic/queue.zig
@@ -16,7 +16,7 @@ pub fn Queue(comptime T: type) type {
             data: T,
         };
 
-        // TODO: well defined copy elision: https://github.com/zig-lang/zig/issues/287
+        // TODO: well defined copy elision: https://github.com/ziglang/zig/issues/287
         pub fn init(self: &Self) void {
             self.root.next = null;
             self.head = &self.root;
diff --git a/std/event.zig b/std/event.zig
index b2e7e3ae381402e10e606e8fdd0ad2e6a3cb4dbf..558bd2a18888b98ea076ec69e210de44796ef74f 100644
--- a/std/event.zig
+++ b/std/event.zig
@@ -148,7 +148,7 @@ pub const Loop = struct {
 };
 
 pub async fn connect(loop: &Loop, _address: &const std.net.Address) !std.os.File {
-    var address = _address.*; // TODO https://github.com/zig-lang/zig/issues/733
+    var address = _address.*; // TODO https://github.com/ziglang/zig/issues/733
 
     const sockfd = try std.os.posixSocket(posix.AF_INET, posix.SOCK_STREAM | posix.SOCK_CLOEXEC | posix.SOCK_NONBLOCK, posix.PROTO_tcp);
     errdefer std.os.close(sockfd);
@@ -172,7 +172,7 @@ test "listen on a port, send bytes, receive bytes" {
 
         async<&mem.Allocator> fn handler(tcp_server: &TcpServer, _addr: &const std.net.Address, _socket: &const std.os.File) void {
             const self = @fieldParentPtr(Self, "tcp_server", tcp_server);
-            var socket = _socket.*; // TODO https://github.com/zig-lang/zig/issues/733
+            var socket = _socket.*; // TODO https://github.com/ziglang/zig/issues/733
             defer socket.close();
             const next_handler = async errorableHandler(self, _addr, socket) catch |err| switch (err) {
                 error.OutOfMemory => @panic("unable to handle connection: out of memory"),
@@ -186,8 +186,8 @@ test "listen on a port, send bytes, receive bytes" {
         }
 
         async fn errorableHandler(self: &Self, _addr: &const std.net.Address, _socket: &const std.os.File) !void {
-            const addr = _addr.*; // TODO https://github.com/zig-lang/zig/issues/733
-            var socket = _socket.*; // TODO https://github.com/zig-lang/zig/issues/733
+            const addr = _addr.*; // TODO https://github.com/ziglang/zig/issues/733
+            var socket = _socket.*; // TODO https://github.com/ziglang/zig/issues/733
 
             var adapter = std.io.FileOutStream.init(&socket);
             var stream = &adapter.stream;
diff --git a/std/fmt/index.zig b/std/fmt/index.zig
index 0af772b7dcff065445d49ffde9fc845b0cb9bb9a..624751822a32c1fa22e820f6a9f63c26817c30a5 100644
--- a/std/fmt/index.zig
+++ b/std/fmt/index.zig
@@ -824,7 +824,7 @@ test "fmt.format" {
     try testFmt("file size: 63MiB\n", "file size: {Bi}\n", usize(63 * 1024 * 1024));
     try testFmt("file size: 66.06MB\n", "file size: {B2}\n", usize(63 * 1024 * 1024));
     {
-        // Dummy field because of https://github.com/zig-lang/zig/issues/557.
+        // Dummy field because of https://github.com/ziglang/zig/issues/557.
         const Struct = struct {
             unused: u8,
         };
diff --git a/std/mem.zig b/std/mem.zig
index 3ca87b35d39ce526e048ea5244ce119d7a5f1bd9..617c1de2f5da5fad23b988ea077edbe2bfa66f4b 100644
--- a/std/mem.zig
+++ b/std/mem.zig
@@ -702,7 +702,7 @@ test "std.mem.rotate" {
     }));
 }
 
-// TODO: When https://github.com/zig-lang/zig/issues/649 is solved these can be done by
+// TODO: When https://github.com/ziglang/zig/issues/649 is solved these can be done by
 // endian-casting the pointer and then dereferencing
 
 pub fn endianSwapIfLe(comptime T: type, x: T) T {
diff --git a/std/os/index.zig b/std/os/index.zig
index 7d19cd82c652d3b185936831034bd9ee3719ce8d..01e2092e1c2d6fe1319f0bcbf39c9d6df090f8a5 100644
--- a/std/os/index.zig
+++ b/std/os/index.zig
@@ -239,7 +239,7 @@ pub fn close(handle: FileHandle) void {
 /// Calls POSIX read, and keeps trying if it gets interrupted.
 pub fn posixRead(fd: i32, buf: []u8) !void {
     // Linux can return EINVAL when read amount is > 0x7ffff000
-    // See https://github.com/zig-lang/zig/pull/743#issuecomment-363158274
+    // See https://github.com/ziglang/zig/pull/743#issuecomment-363158274
     const max_buf_len = 0x7ffff000;
 
     var index: usize = 0;
@@ -281,7 +281,7 @@ pub const PosixWriteError = error{
 /// Calls POSIX write, and keeps trying if it gets interrupted.
 pub fn posixWrite(fd: i32, bytes: []const u8) !void {
     // Linux can return EINVAL when write amount is > 0x7ffff000
-    // See https://github.com/zig-lang/zig/pull/743#issuecomment-363165856
+    // See https://github.com/ziglang/zig/pull/743#issuecomment-363165856
     const max_bytes_len = 0x7ffff000;
 
     var index: usize = 0;
@@ -2513,7 +2513,7 @@ pub const SpawnThreadError = error{
 /// caller must call wait on the returned thread
 pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!&Thread {
     // TODO compile-time call graph analysis to determine stack upper bound
-    // https://github.com/zig-lang/zig/issues/157
+    // https://github.com/ziglang/zig/issues/157
     const default_stack_size = 8 * 1024 * 1024;
 
     const Context = @typeOf(context);
diff --git a/std/os/test.zig b/std/os/test.zig
index 56d6e8b309e3b519367c6988c91a41a17287ee2f..4dfe76224adcf7646bc0ab6d81f96fcb031c2515 100644
--- a/std/os/test.zig
+++ b/std/os/test.zig
@@ -12,7 +12,7 @@ const AtomicOrder = builtin.AtomicOrder;
 test "makePath, put some files in it, deleteTree" {
     if (builtin.os == builtin.Os.windows) {
         // TODO implement os.Dir for windows
-        // https://github.com/zig-lang/zig/issues/709
+        // https://github.com/ziglang/zig/issues/709
         return;
     }
     try os.makePath(a, "os_test_tmp/b/c");
diff --git a/std/os/time.zig b/std/os/time.zig
index 4fd2c4e924b0e965609da1439d858d12ad418512..3af150ab6a5b8ca403da2e8555f1bdd0b1d2da91 100644
--- a/std/os/time.zig
+++ b/std/os/time.zig
@@ -135,7 +135,7 @@ pub const Timer = struct {
     
     //At some point we may change our minds on RAW, but for now we're
     //  sticking with posix standard MONOTONIC. For more information, see: 
-    //  https://github.com/zig-lang/zig/pull/933
+    //  https://github.com/ziglang/zig/pull/933
     //
     //const monotonic_clock_id = switch(builtin.os) {
     //    Os.linux => linux.CLOCK_MONOTONIC_RAW,
diff --git a/std/special/compiler_rt/comparetf2.zig b/std/special/compiler_rt/comparetf2.zig
index c189e5803b7a23952776a266958126f9db4ed404..760c3689c0ab1cf1f37514fe75ff0cbfa7288748 100644
--- a/std/special/compiler_rt/comparetf2.zig
+++ b/std/special/compiler_rt/comparetf2.zig
@@ -1,4 +1,4 @@
-// TODO https://github.com/zig-lang/zig/issues/305
+// TODO https://github.com/ziglang/zig/issues/305
 // and then make the return types of some of these functions the enum instead of c_int
 const LE_LESS = c_int(-1);
 const LE_EQUAL = c_int(0);
@@ -59,7 +59,7 @@ pub extern fn __letf2(a: f128, b: f128) c_int {
     ;
 }
 
-// TODO https://github.com/zig-lang/zig/issues/305
+// TODO https://github.com/ziglang/zig/issues/305
 // and then make the return types of some of these functions the enum instead of c_int
 const GE_LESS = c_int(-1);
 const GE_EQUAL = c_int(0);
diff --git a/std/zig/ast.zig b/std/zig/ast.zig
index c1552b022070ff14d8f27cd24f12ac3580499414..1f15046a79e8910c1364371d4a433952a69d7742 100644
--- a/std/zig/ast.zig
+++ b/std/zig/ast.zig
@@ -113,7 +113,7 @@ pub const Error = union(enum) {
 
     pub fn render(self: &Error, tokens: &Tree.TokenList, stream: var) !void {
         switch (self.*) {
-            // TODO https://github.com/zig-lang/zig/issues/683
+            // TODO https://github.com/ziglang/zig/issues/683
             @TagType(Error).InvalidToken => |*x| return x.render(tokens, stream),
             @TagType(Error).ExpectedVarDeclOrFn => |*x| return x.render(tokens, stream),
             @TagType(Error).ExpectedAggregateKw => |*x| return x.render(tokens, stream),
@@ -137,7 +137,7 @@ pub const Error = union(enum) {
 
     pub fn loc(self: &Error) TokenIndex {
         switch (self.*) {
-            // TODO https://github.com/zig-lang/zig/issues/683
+            // TODO https://github.com/ziglang/zig/issues/683
             @TagType(Error).InvalidToken => |x| return x.token,
             @TagType(Error).ExpectedVarDeclOrFn => |x| return x.token,
             @TagType(Error).ExpectedAggregateKw => |x| return x.token,
diff --git a/test/build_examples.zig b/test/build_examples.zig
index a3b44b91363527d57cdf6c8a0d1350127fa9de67..7a4c0f35d97a51dcb03d3eb4a3a07577553bf009 100644
--- a/test/build_examples.zig
+++ b/test/build_examples.zig
@@ -9,7 +9,7 @@ pub fn addCases(cases: &tests.BuildExamplesContext) void {
     cases.add("example/guess_number/main.zig");
     if (!is_windows) {
         // TODO get this test passing on windows
-        // See https://github.com/zig-lang/zig/issues/538
+        // See https://github.com/ziglang/zig/issues/538
         cases.addBuildFile("example/shared_library/build.zig");
         cases.addBuildFile("example/mix_o_files/build.zig");
     }
diff --git a/test/cases/coroutines.zig b/test/cases/coroutines.zig
index 4aa97861ac97c89c59ebeaab47690da6bc568398..e983947a4c04b4ae2fbb7f5f87e55c141baa34fb 100644
--- a/test/cases/coroutines.zig
+++ b/test/cases/coroutines.zig
@@ -204,7 +204,7 @@ test "error return trace across suspend points - async return" {
     cancel p2;
 }
 
-// TODO https://github.com/zig-lang/zig/issues/760
+// TODO https://github.com/ziglang/zig/issues/760
 fn nonFailing() (promise->error!void) {
     return async suspendThenFail() catch unreachable;
 }
diff --git a/test/cases/misc.zig b/test/cases/misc.zig
index 66487a49467959e58059663be1ad88ed1482d3d3..deeeca8c3a2a1caf289b175da6d55136f8128c3e 100644
--- a/test/cases/misc.zig
+++ b/test/cases/misc.zig
@@ -543,7 +543,7 @@ test "@typeName" {
     comptime {
         assert(mem.eql(u8, @typeName(i64), "i64"));
         assert(mem.eql(u8, @typeName(&usize), "&usize"));
-        // https://github.com/zig-lang/zig/issues/675
+        // https://github.com/ziglang/zig/issues/675
         assert(mem.eql(u8, @typeName(TypeFromFn(u8)), "TypeFromFn(u8)"));
         assert(mem.eql(u8, @typeName(Struct), "Struct"));
         assert(mem.eql(u8, @typeName(Union), "Union"));
diff --git a/test/compare_output.zig b/test/compare_output.zig
index b01e87d4eb819f10662ff045787393163d713a4a..905ffd37a944ec469c57477b7bef28204737ff98 100644
--- a/test/compare_output.zig
+++ b/test/compare_output.zig
@@ -131,7 +131,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) void {
         \\const is_windows = builtin.os == builtin.Os.windows;
         \\const c = @cImport({
         \\    if (is_windows) {
-        \\        // See https://github.com/zig-lang/zig/issues/515
+        \\        // See https://github.com/ziglang/zig/issues/515
         \\        @cDefine("_NO_CRT_STDIO_INLINE", "1");
         \\        @cInclude("io.h");
         \\        @cInclude("fcntl.h");
@@ -316,7 +316,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) void {
         \\const is_windows = builtin.os == builtin.Os.windows;
         \\const c = @cImport({
         \\    if (is_windows) {
-        \\        // See https://github.com/zig-lang/zig/issues/515
+        \\        // See https://github.com/ziglang/zig/issues/515
         \\        @cDefine("_NO_CRT_STDIO_INLINE", "1");
         \\        @cInclude("io.h");
         \\        @cInclude("fcntl.h");
-- 
2.54.0


From b74dda34b6a8b5f04d1865e2f23aab43229815f9 Mon Sep 17 00:00:00 2001
From: Andrew Kelley 
Date: Thu, 24 May 2018 21:51:58 -0400
Subject: [PATCH 37/47] std.zig.tokenizer: support hex escape in char literals

---
 std/zig/parser_test.zig | 13 +++++++++++++
 std/zig/tokenizer.zig   | 34 ++++++++++++++++++++++++++++++++++
 2 files changed, 47 insertions(+)

diff --git a/std/zig/parser_test.zig b/std/zig/parser_test.zig
index c11db787757eadc3dbe24f06c7875f1a367dad40..d114179bf70bcf7952888c1a588bbdad084687a2 100644
--- a/std/zig/parser_test.zig
+++ b/std/zig/parser_test.zig
@@ -1,3 +1,16 @@
+test "zig fmt: float literal with exponent" {
+    try testCanonical(
+        \\test "aoeu" {
+        \\    switch (state) {
+        \\        TermState.Start => switch (c) {
+        \\            '\x1b' => state = TermState.Escape,
+        \\            else => try out.writeByte(c),
+        \\        },
+        \\    }
+        \\}
+        \\
+    );
+}
 test "zig fmt: float literal with exponent" {
     try testCanonical(
         \\pub const f64_true_min = 4.94065645841246544177e-324;
diff --git a/std/zig/tokenizer.zig b/std/zig/tokenizer.zig
index afea7fc899d637a0c95099b933fbf988a951f324..f4cd847dff65be10beceedb5b91139208f138705 100644
--- a/std/zig/tokenizer.zig
+++ b/std/zig/tokenizer.zig
@@ -220,6 +220,8 @@ pub const Tokenizer = struct {
         MultilineStringLiteralLineBackslash,
         CharLiteral,
         CharLiteralBackslash,
+        CharLiteralEscape1,
+        CharLiteralEscape2,
         CharLiteralEnd,
         Backslash,
         Equal,
@@ -612,11 +614,34 @@ pub const Tokenizer = struct {
                         result.id = Token.Id.Invalid;
                         break;
                     },
+                    'x' => {
+                        state = State.CharLiteralEscape1;
+                    },
                     else => {
                         state = State.CharLiteralEnd;
                     },
                 },
 
+                State.CharLiteralEscape1 => switch (c) {
+                    '0'...'9', 'a'...'z', 'A'...'F' => {
+                        state = State.CharLiteralEscape2;
+                    },
+                    else => {
+                        result.id = Token.Id.Invalid;
+                        break;
+                    },
+                },
+
+                State.CharLiteralEscape2 => switch (c) {
+                    '0'...'9', 'a'...'z', 'A'...'F' => {
+                        state = State.CharLiteralEnd;
+                    },
+                    else => {
+                        result.id = Token.Id.Invalid;
+                        break;
+                    },
+                },
+
                 State.CharLiteralEnd => switch (c) {
                     '\'' => {
                         result.id = Token.Id.CharLiteral;
@@ -988,6 +1013,8 @@ pub const Tokenizer = struct {
                 State.MultilineStringLiteralLineBackslash,
                 State.CharLiteral,
                 State.CharLiteralBackslash,
+                State.CharLiteralEscape1,
+                State.CharLiteralEscape2,
                 State.CharLiteralEnd,
                 State.StringLiteralBackslash => {
                     result.id = Token.Id.Invalid;
@@ -1127,6 +1154,13 @@ test "tokenizer" {
     });
 }
 
+test "tokenizer - char literal with hex escape" {
+    testTokenize( \\'\x1b'
+    , []Token.Id {
+        Token.Id.CharLiteral,
+    });
+}
+
 test "tokenizer - float literal e exponent" {
     testTokenize("a = 4.94065645841246544177e-324;\n", []Token.Id {
         Token.Id.Identifier,
-- 
2.54.0


From e6afea99a9642a4fe12b65ef94fee0ee34d7a36b Mon Sep 17 00:00:00 2001
From: Andrew Kelley 
Date: Fri, 25 May 2018 00:37:58 -0400
Subject: [PATCH 38/47] zig fmt: support aligned ptr with bit fields

---
 std/zig/ast.zig         | 22 ++++++++++++++-----
 std/zig/parse.zig       | 48 +++++++++++++++++++++++++++++++++--------
 std/zig/parser_test.zig |  9 ++++++++
 std/zig/render.zig      | 48 ++++++++++++++++++++++++++++++++---------
 4 files changed, 103 insertions(+), 24 deletions(-)

diff --git a/std/zig/ast.zig b/std/zig/ast.zig
index 1f15046a79e8910c1364371d4a433952a69d7742..6c848b4a549fe94bf9a13f9d4fb374455661e615 100644
--- a/std/zig/ast.zig
+++ b/std/zig/ast.zig
@@ -98,6 +98,7 @@ pub const Error = union(enum) {
     UnattachedDocComment: UnattachedDocComment,
     ExpectedEqOrSemi: ExpectedEqOrSemi,
     ExpectedSemiOrLBrace: ExpectedSemiOrLBrace,
+    ExpectedColonOrRParen: ExpectedColonOrRParen,
     ExpectedLabelable: ExpectedLabelable,
     ExpectedInlinable: ExpectedInlinable,
     ExpectedAsmOutputReturnOrType: ExpectedAsmOutputReturnOrType,
@@ -120,6 +121,7 @@ pub const Error = union(enum) {
             @TagType(Error).UnattachedDocComment => |*x| return x.render(tokens, stream),
             @TagType(Error).ExpectedEqOrSemi => |*x| return x.render(tokens, stream),
             @TagType(Error).ExpectedSemiOrLBrace => |*x| return x.render(tokens, stream),
+            @TagType(Error).ExpectedColonOrRParen => |*x| return x.render(tokens, stream),
             @TagType(Error).ExpectedLabelable => |*x| return x.render(tokens, stream),
             @TagType(Error).ExpectedInlinable => |*x| return x.render(tokens, stream),
             @TagType(Error).ExpectedAsmOutputReturnOrType => |*x| return x.render(tokens, stream),
@@ -144,6 +146,7 @@ pub const Error = union(enum) {
             @TagType(Error).UnattachedDocComment => |x| return x.token,
             @TagType(Error).ExpectedEqOrSemi => |x| return x.token,
             @TagType(Error).ExpectedSemiOrLBrace => |x| return x.token,
+            @TagType(Error).ExpectedColonOrRParen => |x| return x.token,
             @TagType(Error).ExpectedLabelable => |x| return x.token,
             @TagType(Error).ExpectedInlinable => |x| return x.token,
             @TagType(Error).ExpectedAsmOutputReturnOrType => |x| return x.token,
@@ -164,6 +167,7 @@ pub const Error = union(enum) {
     pub const ExpectedAggregateKw = SingleTokenError("Expected " ++ @tagName(Token.Id.Keyword_struct) ++ ", " ++ @tagName(Token.Id.Keyword_union) ++ ", or " ++ @tagName(Token.Id.Keyword_enum) ++ ", found {}");
     pub const ExpectedEqOrSemi = SingleTokenError("Expected '=' or ';', found {}");
     pub const ExpectedSemiOrLBrace = SingleTokenError("Expected ';' or '{{', found {}");
+    pub const ExpectedColonOrRParen = SingleTokenError("Expected ':' or ')', found {}");
     pub const ExpectedLabelable = SingleTokenError("Expected 'while', 'for', 'inline', 'suspend', or '{{', found {}");
     pub const ExpectedInlinable = SingleTokenError("Expected 'while' or 'for', found {}");
     pub const ExpectedAsmOutputReturnOrType = SingleTokenError("Expected '->' or " ++ @tagName(Token.Id.Identifier) ++ ", found {}");
@@ -1487,7 +1491,7 @@ pub const Node = struct {
         op: Op,
         rhs: &Node,
 
-        const Op = union(enum) {
+        pub const Op = union(enum) {
             AddrOf: AddrOfInfo,
             ArrayType: &Node,
             Await,
@@ -1504,12 +1508,20 @@ pub const Node = struct {
             UnwrapMaybe,
         };
 
-        const AddrOfInfo = struct {
-            align_expr: ?&Node,
-            bit_offset_start_token: ?TokenIndex,
-            bit_offset_end_token: ?TokenIndex,
+        pub const AddrOfInfo = struct {
+            align_info: ?Align,
             const_token: ?TokenIndex,
             volatile_token: ?TokenIndex,
+
+            pub const Align = struct {
+                node: &Node,
+                bit_range: ?BitRange,
+
+                pub const BitRange = struct {
+                    start: &Node,
+                    end: &Node,
+                };
+            };
         };
 
         pub fn iterate(self: &PrefixOp, index: usize) ?&Node {
diff --git a/std/zig/parse.zig b/std/zig/parse.zig
index 826ea2c3e1ab6cba30647feefbbb89a87bece1de..d60f03c55e4773386dc5020522a5cf4b5452ef26 100644
--- a/std/zig/parse.zig
+++ b/std/zig/parse.zig
@@ -1450,9 +1450,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
             State.SliceOrArrayType => |node| {
                 if (eatToken(&tok_it, &tree, Token.Id.RBracket)) |_| {
                     node.op = ast.Node.PrefixOp.Op{ .SliceType = ast.Node.PrefixOp.AddrOfInfo{
-                        .align_expr = null,
-                        .bit_offset_start_token = null,
-                        .bit_offset_end_token = null,
+                        .align_info = null,
                         .const_token = null,
                         .volatile_token = null,
                     } };
@@ -1467,6 +1465,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
                 try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.op.ArrayType } });
                 continue;
             },
+
             State.AddrOfModifiers => |addr_of_info| {
                 const token = nextToken(&tok_it, &tree);
                 const token_index = token.index;
@@ -1474,12 +1473,19 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
                 switch (token_ptr.id) {
                     Token.Id.Keyword_align => {
                         stack.append(state) catch unreachable;
-                        if (addr_of_info.align_expr != null) {
+                        if (addr_of_info.align_info != null) {
                             ((try tree.errors.addOne())).* = Error{ .ExtraAlignQualifier = Error.ExtraAlignQualifier{ .token = token_index } };
                             return tree;
                         }
-                        try stack.append(State{ .ExpectToken = Token.Id.RParen });
-                        try stack.append(State{ .Expression = OptionalCtx{ .RequiredNull = &addr_of_info.align_expr } });
+                        addr_of_info.align_info = ast.Node.PrefixOp.AddrOfInfo.Align {
+                            .node = undefined,
+                            .bit_range = null,
+                        };
+                        // TODO https://github.com/ziglang/zig/issues/1022
+                        const align_info = &??addr_of_info.align_info;
+
+                        try stack.append(State{ .AlignBitRange = align_info });
+                        try stack.append(State{ .Expression = OptionalCtx{ .Required = &align_info.node } });
                         try stack.append(State{ .ExpectToken = Token.Id.LParen });
                         continue;
                     },
@@ -1508,6 +1514,31 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
                 }
             },
 
+            State.AlignBitRange => |align_info| {
+                const token = nextToken(&tok_it, &tree);
+                switch (token.ptr.id) {
+                    Token.Id.Colon => {
+                        align_info.bit_range = ast.Node.PrefixOp.AddrOfInfo.Align.BitRange(undefined);
+                        const bit_range = &??align_info.bit_range;
+
+                        try stack.append(State{ .ExpectToken = Token.Id.RParen });
+                        try stack.append(State{ .Expression = OptionalCtx{ .Required = &bit_range.end } });
+                        try stack.append(State{ .ExpectToken = Token.Id.Colon });
+                        try stack.append(State{ .Expression = OptionalCtx{ .Required = &bit_range.start } });
+                        continue;
+                    },
+                    Token.Id.RParen => continue,
+                    else => {
+                        (try tree.errors.addOne()).* = Error{
+                            .ExpectedColonOrRParen = Error.ExpectedColonOrRParen{
+                                .token = token.index,
+                            }
+                        };
+                        return tree;
+                    },
+                }
+            },
+
             State.Payload => |opt_ctx| {
                 const token = nextToken(&tok_it, &tree);
                 const token_index = token.index;
@@ -2801,6 +2832,7 @@ const State = union(enum) {
     SliceOrArrayAccess: &ast.Node.SuffixOp,
     SliceOrArrayType: &ast.Node.PrefixOp,
     AddrOfModifiers: &ast.Node.PrefixOp.AddrOfInfo,
+    AlignBitRange: &ast.Node.PrefixOp.AddrOfInfo.Align,
 
     Payload: OptionalCtx,
     PointerPayload: OptionalCtx,
@@ -3120,9 +3152,7 @@ fn tokenIdToPrefixOp(id: @TagType(Token.Id)) ?ast.Node.PrefixOp.Op {
         Token.Id.Asterisk,
         Token.Id.AsteriskAsterisk => ast.Node.PrefixOp.Op{ .PointerType = void{} },
         Token.Id.Ampersand => ast.Node.PrefixOp.Op{ .AddrOf = ast.Node.PrefixOp.AddrOfInfo{
-            .align_expr = null,
-            .bit_offset_start_token = null,
-            .bit_offset_end_token = null,
+            .align_info = null,
             .const_token = null,
             .volatile_token = null,
         } },
diff --git a/std/zig/parser_test.zig b/std/zig/parser_test.zig
index d114179bf70bcf7952888c1a588bbdad084687a2..a29b8c25477f6b2e5b60410217a128946344533b 100644
--- a/std/zig/parser_test.zig
+++ b/std/zig/parser_test.zig
@@ -1,3 +1,12 @@
+test "zig fmt: float literal with exponent" {
+    try testCanonical(
+        \\test "bit field alignment" {
+        \\    assert(@typeOf(&blah.b) == &align(1:3:6) const u3);
+        \\}
+        \\
+    );
+}
+
 test "zig fmt: float literal with exponent" {
     try testCanonical(
         \\test "aoeu" {
diff --git a/std/zig/render.zig b/std/zig/render.zig
index f48b13c987ef65970d5d1b752676be64ecbd83da..3940a61fc1dbb8ba20a62514e697241f18729941 100644
--- a/std/zig/render.zig
+++ b/std/zig/render.zig
@@ -253,17 +253,30 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
             switch (prefix_op_node.op) {
                 ast.Node.PrefixOp.Op.AddrOf => |addr_of_info| {
                     try renderToken(tree, stream, prefix_op_node.op_token, indent, Space.None); // &
-                    if (addr_of_info.align_expr) |align_expr| {
+                    if (addr_of_info.align_info) |align_info| {
                         const align_token = tree.nextToken(prefix_op_node.op_token);
                         try renderToken(tree, stream, align_token, indent, Space.None); // align
 
-                        const lparen_token = tree.prevToken(align_expr.firstToken());
+                        const lparen_token = tree.prevToken(align_info.node.firstToken());
                         try renderToken(tree, stream, lparen_token, indent, Space.None); // (
 
-                        try renderExpression(allocator, stream, tree, indent, align_expr, Space.None);
+                        try renderExpression(allocator, stream, tree, indent, align_info.node, Space.None);
 
-                        const rparen_token = tree.nextToken(align_expr.lastToken());
-                        try renderToken(tree, stream, rparen_token, indent, Space.Space); // )
+                        if (align_info.bit_range) |bit_range| {
+                            const colon1 = tree.prevToken(bit_range.start.firstToken());
+                            const colon2 = tree.prevToken(bit_range.end.firstToken());
+
+                            try renderToken(tree, stream, colon1, indent, Space.None); // :
+                            try renderExpression(allocator, stream, tree, indent, bit_range.start, Space.None);
+                            try renderToken(tree, stream, colon2, indent, Space.None); // :
+                            try renderExpression(allocator, stream, tree, indent, bit_range.end, Space.None);
+
+                            const rparen_token = tree.nextToken(bit_range.end.lastToken());
+                            try renderToken(tree, stream, rparen_token, indent, Space.Space); // )
+                        } else {
+                            const rparen_token = tree.nextToken(align_info.node.lastToken());
+                            try renderToken(tree, stream, rparen_token, indent, Space.Space); // )
+                        }
                     }
                     if (addr_of_info.const_token) |const_token| {
                         try renderToken(tree, stream, const_token, indent, Space.Space); // const
@@ -272,21 +285,35 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
                         try renderToken(tree, stream, volatile_token, indent, Space.Space); // volatile
                     }
                 },
+
                 ast.Node.PrefixOp.Op.SliceType => |addr_of_info| {
                     try renderToken(tree, stream, prefix_op_node.op_token, indent, Space.None); // [
                     try renderToken(tree, stream, tree.nextToken(prefix_op_node.op_token), indent, Space.None); // ]
 
-                    if (addr_of_info.align_expr) |align_expr| {
+                    if (addr_of_info.align_info) |align_info| {
                         const align_token = tree.nextToken(prefix_op_node.op_token);
                         try renderToken(tree, stream, align_token, indent, Space.None); // align
 
-                        const lparen_token = tree.prevToken(align_expr.firstToken());
+                        const lparen_token = tree.prevToken(align_info.node.firstToken());
                         try renderToken(tree, stream, lparen_token, indent, Space.None); // (
 
-                        try renderExpression(allocator, stream, tree, indent, align_expr, Space.None);
+                        try renderExpression(allocator, stream, tree, indent, align_info.node, Space.None);
 
-                        const rparen_token = tree.nextToken(align_expr.lastToken());
-                        try renderToken(tree, stream, rparen_token, indent, Space.Space); // )
+                        if (align_info.bit_range) |bit_range| {
+                            const colon1 = tree.prevToken(bit_range.start.firstToken());
+                            const colon2 = tree.prevToken(bit_range.end.firstToken());
+
+                            try renderToken(tree, stream, colon1, indent, Space.None); // :
+                            try renderExpression(allocator, stream, tree, indent, bit_range.start, Space.None);
+                            try renderToken(tree, stream, colon2, indent, Space.None); // :
+                            try renderExpression(allocator, stream, tree, indent, bit_range.end, Space.None);
+
+                            const rparen_token = tree.nextToken(bit_range.end.lastToken());
+                            try renderToken(tree, stream, rparen_token, indent, Space.Space); // )
+                        } else {
+                            const rparen_token = tree.nextToken(align_info.node.lastToken());
+                            try renderToken(tree, stream, rparen_token, indent, Space.Space); // )
+                        }
                     }
                     if (addr_of_info.const_token) |const_token| {
                         try renderToken(tree, stream, const_token, indent, Space.Space);
@@ -295,6 +322,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
                         try renderToken(tree, stream, volatile_token, indent, Space.Space);
                     }
                 },
+
                 ast.Node.PrefixOp.Op.ArrayType => |array_index| {
                     try renderToken(tree, stream, prefix_op_node.op_token, indent, Space.None); // [
                     try renderExpression(allocator, stream, tree, indent, array_index, Space.None);
-- 
2.54.0


From ca49b6f6b4ffa3ff4324a45501eef98848a2d141 Mon Sep 17 00:00:00 2001
From: Andrew Kelley 
Date: Fri, 25 May 2018 00:39:05 -0400
Subject: [PATCH 39/47] struct fields with no explicit type are not supported

the c++ codebase lets it slide

the self hosted parser correctly reports a parse error
---
 test/cases/syntax.zig | 1 -
 1 file changed, 1 deletion(-)

diff --git a/test/cases/syntax.zig b/test/cases/syntax.zig
index 6c851c0ff39c3ed8bab2e039995f0b4b395cfd26..140a86d5c133e430de4f76faa884ad126d5dbab8 100644
--- a/test/cases/syntax.zig
+++ b/test/cases/syntax.zig
@@ -2,7 +2,6 @@
 
 const struct_trailing_comma = struct { x: i32, y: i32, };
 const struct_no_comma = struct { x: i32, y: i32 };
-const struct_no_comma_void_type = struct { x: i32, y };
 const struct_fn_no_comma = struct { fn m() void {} y: i32 };
 
 const enum_no_comma = enum { A, B };
-- 
2.54.0


From dfc3e11748615f10cf6958c61a934ef852b5aa94 Mon Sep 17 00:00:00 2001
From: Andrew Kelley 
Date: Fri, 25 May 2018 01:03:15 -0400
Subject: [PATCH 40/47] zig fmt: fix handling of comments at top of file

---
 std/zig/parse.zig       |  7 +++++++
 std/zig/parser_test.zig | 20 ++++++++++++++++++++
 std/zig/render.zig      | 16 +++++++++++++++-
 3 files changed, 42 insertions(+), 1 deletion(-)

diff --git a/std/zig/parse.zig b/std/zig/parse.zig
index d60f03c55e4773386dc5020522a5cf4b5452ef26..5d6897a0bca506c21c8ba8525e8f7c134fb34140 100644
--- a/std/zig/parse.zig
+++ b/std/zig/parse.zig
@@ -41,6 +41,13 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
     }
     var tok_it = tree.tokens.iterator(0);
 
+    // skip over line comments at the top of the file
+    while (true) {
+        const next_tok = tok_it.peek() ?? break;
+        if (next_tok.id != Token.Id.LineComment) break;
+        _ = tok_it.next();
+    }
+
     try stack.append(State.TopLevel);
 
     while (true) {
diff --git a/std/zig/parser_test.zig b/std/zig/parser_test.zig
index a29b8c25477f6b2e5b60410217a128946344533b..bd1d142a235b91085ebe28c36057a0aa358c434e 100644
--- a/std/zig/parser_test.zig
+++ b/std/zig/parser_test.zig
@@ -1,3 +1,23 @@
+test "zig fmt: first thing in file is line comment" {
+    try testCanonical(
+        \\// Introspection and determination of system libraries needed by zig.
+        \\
+        \\// Introspection and determination of system libraries needed by zig.
+        \\
+        \\const std = @import("std");
+        \\
+    );
+}
+
+test "zig fmt: line comment after doc comment" {
+    try testCanonical(
+        \\/// doc comment
+        \\// line comment
+        \\fn foo() void {}
+        \\
+    );
+}
+
 test "zig fmt: float literal with exponent" {
     try testCanonical(
         \\test "bit field alignment" {
diff --git a/std/zig/render.zig b/std/zig/render.zig
index 3940a61fc1dbb8ba20a62514e697241f18729941..c2545bddfde1047befe80d5b8855b45ac95a0df7 100644
--- a/std/zig/render.zig
+++ b/std/zig/render.zig
@@ -15,6 +15,20 @@ pub const Error = error{
 pub fn render(allocator: &mem.Allocator, stream: var, tree: &ast.Tree) (@typeOf(stream).Child.Error || Error)!void {
     comptime assert(@typeId(@typeOf(stream)) == builtin.TypeId.Pointer);
 
+    // render all the line comments at the beginning of the file
+    var tok_it = tree.tokens.iterator(0);
+    while (tok_it.next()) |token| {
+        if (token.id != Token.Id.LineComment) break;
+        try stream.print("{}\n", tree.tokenSlicePtr(token));
+        if (tok_it.peek()) |next_token| {
+            const loc = tree.tokenLocationPtr(token.end, next_token);
+            if (loc.line >= 2) {
+                try stream.writeByte('\n');
+            }
+        }
+    }
+
+
     var it = tree.root_node.decls.iterator(0);
     while (it.next()) |decl| {
         try renderTopLevelDecl(allocator, stream, tree, 0, decl.*);
@@ -1455,7 +1469,7 @@ fn renderDocComments(tree: &ast.Tree, stream: var, node: var, indent: usize) (@t
     const comment = node.doc_comments ?? return;
     var it = comment.lines.iterator(0);
     while (it.next()) |line_token_index| {
-        try stream.print("{}\n", tree.tokenSlice(line_token_index.*));
+        try renderToken(tree, stream, line_token_index.*, indent, Space.Newline);
         try stream.writeByteNTimes(' ', indent);
     }
 }
-- 
2.54.0


From 08f95d0c2fac127558c84f7dfb469ac43fb4f425 Mon Sep 17 00:00:00 2001
From: Andrew Kelley 
Date: Fri, 25 May 2018 01:10:54 -0400
Subject: [PATCH 41/47] enum fields with a type are not supported

the c++ codebase lets it slide

the self hosted parser correctly reports a parse error
---
 test/cases/syntax.zig | 1 -
 1 file changed, 1 deletion(-)

diff --git a/test/cases/syntax.zig b/test/cases/syntax.zig
index 140a86d5c133e430de4f76faa884ad126d5dbab8..9512834f5aec190536f70e670d8ab29f99e8ad7c 100644
--- a/test/cases/syntax.zig
+++ b/test/cases/syntax.zig
@@ -5,7 +5,6 @@ const struct_no_comma = struct { x: i32, y: i32 };
 const struct_fn_no_comma = struct { fn m() void {} y: i32 };
 
 const enum_no_comma = enum { A, B };
-const enum_no_comma_type = enum { A, B: i32 };
 
 fn container_init() void {
     const S = struct { x: i32, y: i32 };
-- 
2.54.0


From 000c01a36aeef162d743ebf4bd8ee67380f26672 Mon Sep 17 00:00:00 2001
From: Andrew Kelley 
Date: Fri, 25 May 2018 01:45:14 -0400
Subject: [PATCH 42/47] zig fmt: handle missing trailing comma in array
 literals

---
 std/zig/parser_test.zig | 20 ++++++++++++++++
 std/zig/render.zig      | 52 ++++++++++++++++++++++++-----------------
 2 files changed, 50 insertions(+), 22 deletions(-)

diff --git a/std/zig/parser_test.zig b/std/zig/parser_test.zig
index bd1d142a235b91085ebe28c36057a0aa358c434e..cabfb48387c0cd84d5dfcb46f4388eea22d699ba 100644
--- a/std/zig/parser_test.zig
+++ b/std/zig/parser_test.zig
@@ -1,3 +1,23 @@
+test "zig fmt: first thing in file is line comment" {
+    try testTransform(
+        \\comptime {
+        \\    return []u16{'m', 's', 'y', 's', '-' // hi
+        \\   };
+        \\}
+    ,
+        \\comptime {
+        \\    return []u16{
+        \\        'm',
+        \\        's',
+        \\        'y',
+        \\        's',
+        \\        '-', // hi
+        \\    };
+        \\}
+        \\
+    );
+}
+
 test "zig fmt: first thing in file is line comment" {
     try testCanonical(
         \\// Introspection and determination of system libraries needed by zig.
diff --git a/std/zig/render.zig b/std/zig/render.zig
index c2545bddfde1047befe80d5b8855b45ac95a0df7..87debcb5f0228ce1c3a4b7100cf4b80b7366b5b7 100644
--- a/std/zig/render.zig
+++ b/std/zig/render.zig
@@ -490,13 +490,16 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
                     var it = exprs.iterator(0);
                     while (it.next()) |expr| {
                         try stream.writeByteNTimes(' ', new_indent);
-                        try renderExpression(allocator, stream, tree, new_indent, expr.*, Space.None);
-
-                        const comma = tree.nextToken(expr.*.lastToken());
-                        try renderToken(tree, stream, comma, new_indent, Space.Newline); // ,
 
                         if (it.peek()) |next_expr| {
+                            try renderExpression(allocator, stream, tree, new_indent, expr.*, Space.None);
+
+                            const comma = tree.nextToken(expr.*.lastToken());
+                            try renderToken(tree, stream, comma, new_indent, Space.Newline); // ,
+
                             try renderExtraNewline(tree, stream, next_expr.*);
+                        } else {
+                            try renderTrailingComma(allocator, stream, tree, indent, expr.*, Space.Newline);
                         }
                     }
 
@@ -950,24 +953,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
                 try renderExpression(allocator, stream, tree, indent, payload, Space.Space);
             }
 
-            // add a trailing comma if necessary
-            const end_token = switch_case.lastToken() + 1;
-            switch (tree.tokens.at(end_token).id) {
-                Token.Id.Comma => {
-                    try renderExpression(allocator, stream, tree, indent, switch_case.expr, Space.None);
-                    try renderToken(tree, stream, end_token, indent, space); // ,
-                },
-                Token.Id.LineComment => {
-                    try renderExpression(allocator, stream, tree, indent, switch_case.expr, Space.NoComment);
-                    try stream.write(", ");
-                    try renderToken(tree, stream, end_token, indent, space);
-                },
-                else => {
-                    try renderExpression(allocator, stream, tree, indent, switch_case.expr, Space.None);
-                    try stream.write(",\n");
-                    assert(space == Space.Newline);
-                },
-            }
+            try renderTrailingComma(allocator, stream, tree, indent, switch_case.expr, space);
         },
         ast.Node.Id.SwitchElse => {
             const switch_else = @fieldParentPtr(ast.Node.SwitchElse, "base", base);
@@ -1473,3 +1459,25 @@ fn renderDocComments(tree: &ast.Tree, stream: var, node: var, indent: usize) (@t
         try stream.writeByteNTimes(' ', indent);
     }
 }
+
+fn renderTrailingComma(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent: usize, base: &ast.Node,
+    space: Space) (@typeOf(stream).Child.Error || Error)!void
+{
+    const end_token = base.lastToken() + 1;
+    switch (tree.tokens.at(end_token).id) {
+        Token.Id.Comma => {
+            try renderExpression(allocator, stream, tree, indent, base, Space.None);
+            try renderToken(tree, stream, end_token, indent, space); // ,
+        },
+        Token.Id.LineComment => {
+            try renderExpression(allocator, stream, tree, indent, base, Space.NoComment);
+            try stream.write(", ");
+            try renderToken(tree, stream, end_token, indent, space);
+        },
+        else => {
+            try renderExpression(allocator, stream, tree, indent, base, Space.None);
+            try stream.write(",\n");
+            assert(space == Space.Newline);
+        },
+    }
+}
-- 
2.54.0


From 3f302f841136ebbcc4da0707fff6faaac4c03e55 Mon Sep 17 00:00:00 2001
From: Andrew Kelley 
Date: Fri, 25 May 2018 01:52:59 -0400
Subject: [PATCH 43/47] handle more cases of inserting trailing commas

---
 std/zig/render.zig | 20 +++++++++++++-------
 1 file changed, 13 insertions(+), 7 deletions(-)

diff --git a/std/zig/render.zig b/std/zig/render.zig
index 87debcb5f0228ce1c3a4b7100cf4b80b7366b5b7..61c66aaaf830724bed803aeea13db2174913face 100644
--- a/std/zig/render.zig
+++ b/std/zig/render.zig
@@ -449,13 +449,16 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
                     var it = field_inits.iterator(0);
                     while (it.next()) |field_init| {
                         try stream.writeByteNTimes(' ', new_indent);
-                        try renderExpression(allocator, stream, tree, new_indent, field_init.*, Space.None);
-
-                        const comma = tree.nextToken(field_init.*.lastToken());
-                        try renderToken(tree, stream, comma, new_indent, Space.Newline);
 
                         if (it.peek()) |next_field_init| {
+                            try renderExpression(allocator, stream, tree, new_indent, field_init.*, Space.None);
+
+                            const comma = tree.nextToken(field_init.*.lastToken());
+                            try renderToken(tree, stream, comma, new_indent, Space.Newline);
+
                             try renderExtraNewline(tree, stream, next_field_init.*);
+                        } else {
+                            try renderTrailingComma(allocator, stream, tree, new_indent, field_init.*, Space.Newline);
                         }
                     }
 
@@ -499,7 +502,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
 
                             try renderExtraNewline(tree, stream, next_expr.*);
                         } else {
-                            try renderTrailingComma(allocator, stream, tree, indent, expr.*, Space.Newline);
+                            try renderTrailingComma(allocator, stream, tree, new_indent, expr.*, Space.Newline);
                         }
                     }
 
@@ -743,11 +746,14 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
             var it = err_set_decl.decls.iterator(0);
             while (it.next()) |node| {
                 try stream.writeByteNTimes(' ', new_indent);
-                try renderExpression(allocator, stream, tree, new_indent, node.*, Space.None);
-                try renderToken(tree, stream, tree.nextToken(node.*.lastToken()), new_indent, Space.Newline); // ,
 
                 if (it.peek()) |next_node| {
+                    try renderExpression(allocator, stream, tree, new_indent, node.*, Space.None);
+                    try renderToken(tree, stream, tree.nextToken(node.*.lastToken()), new_indent, Space.Newline); // ,
+
                     try renderExtraNewline(tree, stream, next_node.*);
+                } else {
+                    try renderTrailingComma(allocator, stream, tree, new_indent, node.*, Space.Newline);
                 }
             }
 
-- 
2.54.0


From 56cb7f1740bf369b7cd2cac29db559c5c6bccc22 Mon Sep 17 00:00:00 2001
From: Andrew Kelley 
Date: Fri, 25 May 2018 02:08:43 -0400
Subject: [PATCH 44/47] update json_test to be compliant with zig source
 encoding

See #663
---
 std/json_test.zig | 60 ++++++++++++-----------------------------------
 1 file changed, 15 insertions(+), 45 deletions(-)

diff --git a/std/json_test.zig b/std/json_test.zig
index 90a2ddbd505f3ea49fc8c66db8df29111392eb6a..60a5d1288ca4d2ff8a3b0820713376d973fc504c 100644
--- a/std/json_test.zig
+++ b/std/json_test.zig
@@ -431,15 +431,11 @@ test "y_string_two-byte-utf-8" {
 }
 
 test "y_string_u+2028_line_sep" {
-    ok(
-        \\["
"]
-    );
+    ok("[\"\xe2\x80\xa8\"]");
 }
 
 test "y_string_u+2029_par_sep" {
-    ok(
-        \\["
"]
-    );
+    ok("[\"\xe2\x80\xa9\"]");
 }
 
 test "y_string_uescaped_newline" {
@@ -455,9 +451,7 @@ test "y_string_uEscape" {
 }
 
 test "y_string_unescaped_char_delete" {
-    ok(
-        \\[""]
-    );
+    ok("[\"\x7f\"]");
 }
 
 test "y_string_unicode_2" {
@@ -527,9 +521,7 @@ test "y_string_utf8" {
 }
 
 test "y_string_with_del_character" {
-    ok(
-        \\["aa"]
-    );
+    ok("[\"a\x7fa\"]");
 }
 
 test "y_structure_lonely_false" {
@@ -718,9 +710,7 @@ test "n_array_number_and_several_commas" {
 }
 
 test "n_array_spaces_vertical_tab_formfeed" {
-    err(
-        \\["a"\f]
-    );
+    err("[\"\x0aa\"\\f]");
 }
 
 test "n_array_star_inside" {
@@ -774,9 +764,7 @@ test "n_incomplete_true" {
 }
 
 test "n_multidigit_number_then_00" {
-    err(
-        \\123
-    );
+    err("123\x00");
 }
 
 test "n_number_0.1.2" {
@@ -1309,9 +1297,7 @@ test "n_string_escaped_ctrl_char_tab" {
 }
 
 test "n_string_escaped_emoji" {
-    err(
-        \\["\🌀"]
-    );
+    err("[\"\x5c\xc3\xb0\xc2\x9f\xc2\x8c\xc2\x80\"]");
 }
 
 test "n_string_escape_x" {
@@ -1357,9 +1343,7 @@ test "n_string_invalid_unicode_escape" {
 }
 
 test "n_string_invalid_utf8_after_escape" {
-    err(
-        \\["\å"]
-    );
+    err("[\"\\\x75\xc3\xa5\"]");
 }
 
 test "n_string_invalid-utf-8-in-escape" {
@@ -1405,9 +1389,7 @@ test "n_string_start_escape_unclosed" {
 }
 
 test "n_string_unescaped_crtl_char" {
-    err(
-        \\["aa"]
-    );
+    err("[\"a\x00a\"]");
 }
 
 test "n_string_unescaped_newline" {
@@ -1418,9 +1400,7 @@ test "n_string_unescaped_newline" {
 }
 
 test "n_string_unescaped_tab" {
-    err(
-        \\["	"]
-    );
+    err("[\"\t\"]");
 }
 
 test "n_string_unicode_CapitalU" {
@@ -1532,9 +1512,7 @@ test "n_structure_no_data" {
 }
 
 test "n_structure_null-byte-outside-string" {
-    err(
-        \\[]
-    );
+    err("[\x00]");
 }
 
 test "n_structure_number_with_trailing_garbage" {
@@ -1718,9 +1696,7 @@ test "n_structure_UTF8_BOM_no_data" {
 }
 
 test "n_structure_whitespace_formfeed" {
-    err(
-        \\[]
-    );
+    err("[\x0c]");
 }
 
 test "n_structure_whitespace_U+2060_word_joiner" {
@@ -1900,21 +1876,15 @@ test "i_string_truncated-utf-8" {
 }
 
 test "i_string_utf16BE_no_BOM" {
-    any(
-        \\["é"]
-    );
+    any("\x00\x5b\x00\x22\x00\xc3\xa9\x00\x22\x00\x5d");
 }
 
 test "i_string_utf16LE_no_BOM" {
-    any(
-        \\["é"]
-    );
+    any("\x5b\x00\x22\x00\xc3\xa9\x00\x22\x00\x5d\x00");
 }
 
 test "i_string_UTF-16LE_with_BOM" {
-    any(
-        \\ÿþ["é"]
-    );
+    any("\xc3\xbf\xc3\xbe\x5b\x00\x22\x00\xc3\xa9\x00\x22\x00\x5d\x00");
 }
 
 test "i_string_UTF-8_invalid_sequence" {
-- 
2.54.0


From a630d3e851a62c0e8971cbd2183e215606f35ab1 Mon Sep 17 00:00:00 2001
From: Andrew Kelley 
Date: Fri, 25 May 2018 02:19:53 -0400
Subject: [PATCH 45/47] zig fmt: fix rendering of align keyword of slice type

---
 std/zig/parser_test.zig |  9 +++++++++
 std/zig/render.zig      | 12 ++++++------
 2 files changed, 15 insertions(+), 6 deletions(-)

diff --git a/std/zig/parser_test.zig b/std/zig/parser_test.zig
index cabfb48387c0cd84d5dfcb46f4388eea22d699ba..ada132e77509af413a1bd2483d671f128057a612 100644
--- a/std/zig/parser_test.zig
+++ b/std/zig/parser_test.zig
@@ -1,3 +1,12 @@
+test "zig fmt: slice align" {
+    try testCanonical(
+        \\const A = struct {
+        \\    items: []align(A) T,
+        \\};
+        \\
+    );
+}
+
 test "zig fmt: first thing in file is line comment" {
     try testTransform(
         \\comptime {
diff --git a/std/zig/render.zig b/std/zig/render.zig
index 61c66aaaf830724bed803aeea13db2174913face..215e57ceb801f0d9eae66784e614f05d7f945034 100644
--- a/std/zig/render.zig
+++ b/std/zig/render.zig
@@ -268,10 +268,10 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
                 ast.Node.PrefixOp.Op.AddrOf => |addr_of_info| {
                     try renderToken(tree, stream, prefix_op_node.op_token, indent, Space.None); // &
                     if (addr_of_info.align_info) |align_info| {
-                        const align_token = tree.nextToken(prefix_op_node.op_token);
-                        try renderToken(tree, stream, align_token, indent, Space.None); // align
-
                         const lparen_token = tree.prevToken(align_info.node.firstToken());
+                        const align_token = tree.prevToken(lparen_token);
+
+                        try renderToken(tree, stream, align_token, indent, Space.None); // align
                         try renderToken(tree, stream, lparen_token, indent, Space.None); // (
 
                         try renderExpression(allocator, stream, tree, indent, align_info.node, Space.None);
@@ -305,10 +305,10 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
                     try renderToken(tree, stream, tree.nextToken(prefix_op_node.op_token), indent, Space.None); // ]
 
                     if (addr_of_info.align_info) |align_info| {
-                        const align_token = tree.nextToken(prefix_op_node.op_token);
-                        try renderToken(tree, stream, align_token, indent, Space.None); // align
-
                         const lparen_token = tree.prevToken(align_info.node.firstToken());
+                        const align_token = tree.prevToken(lparen_token);
+
+                        try renderToken(tree, stream, align_token, indent, Space.None); // align
                         try renderToken(tree, stream, lparen_token, indent, Space.None); // (
 
                         try renderExpression(allocator, stream, tree, indent, align_info.node, Space.None);
-- 
2.54.0


From 4405897cbd9105fddb512545594f336b597d91e9 Mon Sep 17 00:00:00 2001
From: Andrew Kelley 
Date: Fri, 25 May 2018 20:34:53 -0400
Subject: [PATCH 46/47] zig fmt: support trailing comma on switch case items

---
 std/zig/parse.zig       | 25 +++++++++++++++--------
 std/zig/parser_test.zig | 35 +++++++++++++++++++++++++-------
 std/zig/render.zig      | 44 +++++++++++++++++++++++++++++++----------
 3 files changed, 79 insertions(+), 25 deletions(-)

diff --git a/std/zig/parse.zig b/std/zig/parse.zig
index 5d6897a0bca506c21c8ba8525e8f7c134fb34140..a6eb22a2d0daae7e1ec81e81e35cac089d1b16b1 100644
--- a/std/zig/parse.zig
+++ b/std/zig/parse.zig
@@ -1325,21 +1325,30 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
                     continue;
                 } else {
                     prevToken(&tok_it, &tree);
-                    try stack.append(State{ .SwitchCaseItem = switch_case });
+                    stack.append(State{ .SwitchCaseItemCommaOrEnd = switch_case }) catch unreachable;
+                    try stack.append(State{ .RangeExpressionBegin = OptionalCtx{ .Required = try switch_case.items.addOne() } });
                     continue;
                 }
             },
-            State.SwitchCaseItem => |node| {
-                stack.append(State{ .SwitchCaseItemCommaOrEnd = node }) catch unreachable;
-                try stack.append(State{ .RangeExpressionBegin = OptionalCtx{ .Required = try node.items.addOne() } });
+            State.SwitchCaseItemOrEnd => |switch_case| {
+                const token = nextToken(&tok_it, &tree);
+                if (token.ptr.id == Token.Id.EqualAngleBracketRight) {
+                    switch_case.arrow_token = token.index;
+                    continue;
+                } else {
+                    prevToken(&tok_it, &tree);
+                    stack.append(State{ .SwitchCaseItemCommaOrEnd = switch_case }) catch unreachable;
+                    try stack.append(State{ .RangeExpressionBegin = OptionalCtx{ .Required = try switch_case.items.addOne() } });
+                    continue;
+                }
             },
-            State.SwitchCaseItemCommaOrEnd => |node| {
+            State.SwitchCaseItemCommaOrEnd => |switch_case| {
                 switch (expectCommaOrEnd(&tok_it, &tree, Token.Id.EqualAngleBracketRight)) {
                     ExpectCommaOrEndResult.end_token => |end_token| {
                         if (end_token) |t| {
-                            node.arrow_token = t;
+                            switch_case.arrow_token = t;
                         } else {
-                            stack.append(State{ .SwitchCaseItem = node }) catch unreachable;
+                            stack.append(State{ .SwitchCaseItemOrEnd = switch_case }) catch unreachable;
                         }
                         continue;
                     },
@@ -2828,8 +2837,8 @@ const State = union(enum) {
     SwitchCaseOrEnd: ListSave(ast.Node.Switch.CaseList),
     SwitchCaseCommaOrEnd: ListSave(ast.Node.Switch.CaseList),
     SwitchCaseFirstItem: &ast.Node.SwitchCase,
-    SwitchCaseItem: &ast.Node.SwitchCase,
     SwitchCaseItemCommaOrEnd: &ast.Node.SwitchCase,
+    SwitchCaseItemOrEnd: &ast.Node.SwitchCase,
 
     SuspendBody: &ast.Node.Suspend,
     AsyncAllocator: &ast.Node.AsyncAttribute,
diff --git a/std/zig/parser_test.zig b/std/zig/parser_test.zig
index ada132e77509af413a1bd2483d671f128057a612..9d5e64a66f50aab38b88c3ad4e79a293c7001ff6 100644
--- a/std/zig/parser_test.zig
+++ b/std/zig/parser_test.zig
@@ -1,3 +1,27 @@
+test "zig fmt: switch cases trailing comma" {
+    try testTransform(
+        \\fn switch_cases(x: i32) void {
+        \\    switch (x) {
+        \\        1,2,3 => {},
+        \\        4,5, => {},
+        \\        6...8, => {},
+        \\        else => {},
+        \\    }
+        \\}
+    ,
+        \\fn switch_cases(x: i32) void {
+        \\    switch (x) {
+        \\        1, 2, 3 => {},
+        \\        4,
+        \\        5, => {},
+        \\        6 ... 8 => {},
+        \\        else => {},
+        \\    }
+        \\}
+        \\
+    );
+}
+
 test "zig fmt: slice align" {
     try testCanonical(
         \\const A = struct {
@@ -7,7 +31,7 @@ test "zig fmt: slice align" {
     );
 }
 
-test "zig fmt: first thing in file is line comment" {
+test "zig fmt: add trailing comma to array literal" {
     try testTransform(
         \\comptime {
         \\    return []u16{'m', 's', 'y', 's', '-' // hi
@@ -217,13 +241,11 @@ test "zig fmt: add comma on last switch prong" {
         \\test "aoeu" {
         \\    switch (self.init_arg_expr) {
         \\        InitArg.Type => |t| {},
-        \\        InitArg.None,
-        \\        InitArg.Enum => {},
+        \\        InitArg.None, InitArg.Enum => {},
         \\    }
         \\    switch (self.init_arg_expr) {
         \\        InitArg.Type => |t| {},
-        \\        InitArg.None,
-        \\        InitArg.Enum => {}, //line comment
+        \\        InitArg.None, InitArg.Enum => {}, //line comment
         \\    }
         \\}
         \\
@@ -1003,8 +1025,7 @@ test "zig fmt: switch" {
         \\    switch (0) {
         \\        0 => {},
         \\        1 => unreachable,
-        \\        2,
-        \\        3 => {},
+        \\        2, 3 => {},
         \\        4 ... 7 => {},
         \\        1 + 4 * 3 + 22 => {},
         \\        else => {
diff --git a/std/zig/render.zig b/std/zig/render.zig
index 215e57ceb801f0d9eae66784e614f05d7f945034..4691d836c3c8743d7126c356f35057a3c0ef463d 100644
--- a/std/zig/render.zig
+++ b/std/zig/render.zig
@@ -939,17 +939,41 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
         ast.Node.Id.SwitchCase => {
             const switch_case = @fieldParentPtr(ast.Node.SwitchCase, "base", base);
 
-            var it = switch_case.items.iterator(0);
-            while (it.next()) |node| {
-                if (it.peek()) |next_node| {
-                    try renderExpression(allocator, stream, tree, indent, node.*, Space.None);
+            assert(switch_case.items.len != 0);
+            const src_has_trailing_comma = blk: {
+                const last_node = switch_case.items.at(switch_case.items.len - 1).*;
+                const maybe_comma = tree.nextToken(last_node.lastToken());
+                break :blk tree.tokens.at(maybe_comma).id == Token.Id.Comma;
+            };
 
-                    const comma_token = tree.nextToken(node.*.lastToken());
-                    try renderToken(tree, stream, comma_token, indent, Space.Newline); // ,
-                    try renderExtraNewline(tree, stream, next_node.*);
-                    try stream.writeByteNTimes(' ', indent);
-                } else {
-                    try renderExpression(allocator, stream, tree, indent, node.*, Space.Space);
+            if (switch_case.items.len == 1 or !src_has_trailing_comma) {
+                var it = switch_case.items.iterator(0);
+                while (it.next()) |node| {
+                    if (it.peek()) |next_node| {
+                        try renderExpression(allocator, stream, tree, indent, node.*, Space.None);
+
+                        const comma_token = tree.nextToken(node.*.lastToken());
+                        try renderToken(tree, stream, comma_token, indent, Space.Space); // ,
+                        try renderExtraNewline(tree, stream, next_node.*);
+                    } else {
+                        try renderExpression(allocator, stream, tree, indent, node.*, Space.Space);
+                    }
+                }
+            } else {
+                var it = switch_case.items.iterator(0);
+                while (true) {
+                    const node = ??it.next();
+                    if (it.peek()) |next_node| {
+                        try renderExpression(allocator, stream, tree, indent, node.*, Space.None);
+
+                        const comma_token = tree.nextToken(node.*.lastToken());
+                        try renderToken(tree, stream, comma_token, indent, Space.Newline); // ,
+                        try renderExtraNewline(tree, stream, next_node.*);
+                        try stream.writeByteNTimes(' ', indent);
+                    } else {
+                        try renderTrailingComma(allocator, stream, tree, indent, node.*, Space.Space);
+                        break;
+                    }
                 }
             }
 
-- 
2.54.0


From c029f4bfc47b5d6d825f7ae7a3f224e9e9d6ce0b Mon Sep 17 00:00:00 2001
From: Andrew Kelley 
Date: Fri, 25 May 2018 20:41:14 -0400
Subject: [PATCH 47/47] trailing comma after var args is not supported

---
 test/cases/syntax.zig | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/test/cases/syntax.zig b/test/cases/syntax.zig
index 9512834f5aec190536f70e670d8ab29f99e8ad7c..20fb6cd2035fa64681da9f9fcfcf656e336284bf 100644
--- a/test/cases/syntax.zig
+++ b/test/cases/syntax.zig
@@ -34,16 +34,11 @@ fn switch_prongs(x: i32) void {
 
 const fn_no_comma = fn(i32, i32)void;
 const fn_trailing_comma = fn(i32, i32,)void;
-const fn_vararg_trailing_comma = fn(i32, i32, ...,)void;
 
 fn fn_calls() void {
     fn add(x: i32, y: i32,) i32 { x + y };
     _ = add(1, 2);
     _ = add(1, 2,);
-
-    fn swallow(x: ...,) void {};
-    _ = swallow(1,2,3,);
-    _ = swallow();
 }
 
 fn asm_lists() void {
-- 
2.54.0