LCOV - code coverage report
Current view: top level - src - ast_render.cpp (source / functions) Hit Total Coverage
Test: coverage.info.cleaned Lines: 0 874 0.0 %
Date: 1970-01-01 00:00:01 Functions: 0 28 0.0 %
Branches: 0 485 0.0 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright (c) 2016 Andrew Kelley
       3                 :            :  *
       4                 :            :  * This file is part of zig, which is MIT licensed.
       5                 :            :  * See http://opensource.org/licenses/MIT
       6                 :            :  */
       7                 :            : 
       8                 :            : #include "analyze.hpp"
       9                 :            : #include "ast_render.hpp"
      10                 :            : #include "os.hpp"
      11                 :            : 
      12                 :            : #include <stdio.h>
      13                 :            : 
      14                 :          0 : static const char *bin_op_str(BinOpType bin_op) {
      15   [ #  #  #  #  :          0 :     switch (bin_op) {
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
      16                 :          0 :         case BinOpTypeInvalid:                return "(invalid)";
      17                 :          0 :         case BinOpTypeBoolOr:                 return "or";
      18                 :          0 :         case BinOpTypeBoolAnd:                return "and";
      19                 :          0 :         case BinOpTypeCmpEq:                  return "==";
      20                 :          0 :         case BinOpTypeCmpNotEq:               return "!=";
      21                 :          0 :         case BinOpTypeCmpLessThan:            return "<";
      22                 :          0 :         case BinOpTypeCmpGreaterThan:         return ">";
      23                 :          0 :         case BinOpTypeCmpLessOrEq:            return "<=";
      24                 :          0 :         case BinOpTypeCmpGreaterOrEq:         return ">=";
      25                 :          0 :         case BinOpTypeBinOr:                  return "|";
      26                 :          0 :         case BinOpTypeBinXor:                 return "^";
      27                 :          0 :         case BinOpTypeBinAnd:                 return "&";
      28                 :          0 :         case BinOpTypeBitShiftLeft:           return "<<";
      29                 :          0 :         case BinOpTypeBitShiftRight:          return ">>";
      30                 :          0 :         case BinOpTypeAdd:                    return "+";
      31                 :          0 :         case BinOpTypeAddWrap:                return "+%";
      32                 :          0 :         case BinOpTypeSub:                    return "-";
      33                 :          0 :         case BinOpTypeSubWrap:                return "-%";
      34                 :          0 :         case BinOpTypeMult:                   return "*";
      35                 :          0 :         case BinOpTypeMultWrap:               return "*%";
      36                 :          0 :         case BinOpTypeDiv:                    return "/";
      37                 :          0 :         case BinOpTypeMod:                    return "%";
      38                 :          0 :         case BinOpTypeAssign:                 return "=";
      39                 :          0 :         case BinOpTypeAssignTimes:            return "*=";
      40                 :          0 :         case BinOpTypeAssignTimesWrap:        return "*%=";
      41                 :          0 :         case BinOpTypeAssignDiv:              return "/=";
      42                 :          0 :         case BinOpTypeAssignMod:              return "%=";
      43                 :          0 :         case BinOpTypeAssignPlus:             return "+=";
      44                 :          0 :         case BinOpTypeAssignPlusWrap:         return "+%=";
      45                 :          0 :         case BinOpTypeAssignMinus:            return "-=";
      46                 :          0 :         case BinOpTypeAssignMinusWrap:        return "-%=";
      47                 :          0 :         case BinOpTypeAssignBitShiftLeft:     return "<<=";
      48                 :          0 :         case BinOpTypeAssignBitShiftRight:    return ">>=";
      49                 :          0 :         case BinOpTypeAssignBitAnd:           return "&=";
      50                 :          0 :         case BinOpTypeAssignBitXor:           return "^=";
      51                 :          0 :         case BinOpTypeAssignBitOr:            return "|=";
      52                 :          0 :         case BinOpTypeAssignMergeErrorSets:   return "||=";
      53                 :          0 :         case BinOpTypeUnwrapOptional:         return "orelse";
      54                 :          0 :         case BinOpTypeArrayCat:               return "++";
      55                 :          0 :         case BinOpTypeArrayMult:              return "**";
      56                 :          0 :         case BinOpTypeErrorUnion:             return "!";
      57                 :          0 :         case BinOpTypeMergeErrorSets:         return "||";
      58                 :            :     }
      59                 :          0 :     zig_unreachable();
      60                 :            : }
      61                 :            : 
      62                 :          0 : static const char *prefix_op_str(PrefixOp prefix_op) {
      63   [ #  #  #  #  :          0 :     switch (prefix_op) {
             #  #  #  # ]
      64                 :          0 :         case PrefixOpInvalid: return "(invalid)";
      65                 :          0 :         case PrefixOpNegation: return "-";
      66                 :          0 :         case PrefixOpNegationWrap: return "-%";
      67                 :          0 :         case PrefixOpBoolNot: return "!";
      68                 :          0 :         case PrefixOpBinNot: return "~";
      69                 :          0 :         case PrefixOpOptional: return "?";
      70                 :          0 :         case PrefixOpAddrOf: return "&";
      71                 :            :     }
      72                 :          0 :     zig_unreachable();
      73                 :            : }
      74                 :            : 
      75                 :          0 : static const char *visib_mod_string(VisibMod mod) {
      76      [ #  #  # ]:          0 :     switch (mod) {
      77                 :          0 :         case VisibModPub: return "pub ";
      78                 :          0 :         case VisibModPrivate: return "";
      79                 :            :     }
      80                 :          0 :     zig_unreachable();
      81                 :            : }
      82                 :            : 
      83                 :          0 : static const char *return_string(ReturnKind kind) {
      84      [ #  #  # ]:          0 :     switch (kind) {
      85                 :          0 :         case ReturnKindUnconditional: return "return";
      86                 :          0 :         case ReturnKindError: return "try";
      87                 :            :     }
      88                 :          0 :     zig_unreachable();
      89                 :            : }
      90                 :            : 
      91                 :          0 : static const char *defer_string(ReturnKind kind) {
      92      [ #  #  # ]:          0 :     switch (kind) {
      93                 :          0 :         case ReturnKindUnconditional: return "defer";
      94                 :          0 :         case ReturnKindError: return "errdefer";
      95                 :            :     }
      96                 :          0 :     zig_unreachable();
      97                 :            : }
      98                 :            : 
      99                 :          0 : static const char *layout_string(ContainerLayout layout) {
     100   [ #  #  #  # ]:          0 :     switch (layout) {
     101                 :          0 :         case ContainerLayoutAuto: return "";
     102                 :          0 :         case ContainerLayoutExtern: return "extern ";
     103                 :          0 :         case ContainerLayoutPacked: return "packed ";
     104                 :            :     }
     105                 :          0 :     zig_unreachable();
     106                 :            : }
     107                 :            : 
     108                 :          0 : static const char *extern_string(bool is_extern) {
     109         [ #  # ]:          0 :     return is_extern ? "extern " : "";
     110                 :            : }
     111                 :            : 
     112                 :          0 : static const char *export_string(bool is_export) {
     113         [ #  # ]:          0 :     return is_export ? "export " : "";
     114                 :            : }
     115                 :            : 
     116                 :            : //static const char *calling_convention_string(CallingConvention cc) {
     117                 :            : //    switch (cc) {
     118                 :            : //        case CallingConventionUnspecified: return "";
     119                 :            : //        case CallingConventionC: return "extern ";
     120                 :            : //        case CallingConventionCold: return "coldcc ";
     121                 :            : //        case CallingConventionNaked: return "nakedcc ";
     122                 :            : //        case CallingConventionStdcall: return "stdcallcc ";
     123                 :            : //    }
     124                 :            : //    zig_unreachable();
     125                 :            : //}
     126                 :            : 
     127                 :          0 : static const char *inline_string(FnInline fn_inline) {
     128   [ #  #  #  # ]:          0 :     switch (fn_inline) {
     129                 :          0 :         case FnInlineAlways: return "inline ";
     130                 :          0 :         case FnInlineNever:  return "noinline ";
     131                 :          0 :         case FnInlineAuto:   return "";
     132                 :            :     }
     133                 :          0 :     zig_unreachable();
     134                 :            : }
     135                 :            : 
     136                 :          0 : static const char *const_or_var_string(bool is_const) {
     137         [ #  # ]:          0 :     return is_const ? "const" : "var";
     138                 :            : }
     139                 :            : 
     140                 :          0 : static const char *thread_local_string(Token *tok) {
     141         [ #  # ]:          0 :     return (tok == nullptr) ? "" : "threadlocal ";
     142                 :            : }
     143                 :            : 
     144                 :          0 : static const char *token_to_ptr_len_str(Token *tok) {
     145                 :          0 :     assert(tok != nullptr);
     146   [ #  #  #  # ]:          0 :     switch (tok->id) {
     147                 :          0 :         case TokenIdStar:
     148                 :            :         case TokenIdStarStar:
     149                 :          0 :             return "*";
     150                 :          0 :         case TokenIdBracketStarBracket:
     151                 :          0 :             return "[*]";
     152                 :          0 :         case TokenIdBracketStarCBracket:
     153                 :          0 :             return "[*c]";
     154                 :          0 :         default:
     155                 :          0 :             zig_unreachable();
     156                 :            :     }
     157                 :            : }
     158                 :            : 
     159                 :          0 : static const char *node_type_str(NodeType node_type) {
     160   [ #  #  #  #  :          0 :     switch (node_type) {
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
     161                 :          0 :         case NodeTypeFnDef:
     162                 :          0 :             return "FnDef";
     163                 :          0 :         case NodeTypeFnProto:
     164                 :          0 :             return "FnProto";
     165                 :          0 :         case NodeTypeParamDecl:
     166                 :          0 :             return "ParamDecl";
     167                 :          0 :         case NodeTypeBlock:
     168                 :          0 :             return "Block";
     169                 :          0 :         case NodeTypeGroupedExpr:
     170                 :          0 :             return "Parens";
     171                 :          0 :         case NodeTypeBinOpExpr:
     172                 :          0 :             return "BinOpExpr";
     173                 :          0 :         case NodeTypeCatchExpr:
     174                 :          0 :             return "CatchExpr";
     175                 :          0 :         case NodeTypeFnCallExpr:
     176                 :          0 :             return "FnCallExpr";
     177                 :          0 :         case NodeTypeArrayAccessExpr:
     178                 :          0 :             return "ArrayAccessExpr";
     179                 :          0 :         case NodeTypeSliceExpr:
     180                 :          0 :             return "SliceExpr";
     181                 :          0 :         case NodeTypeReturnExpr:
     182                 :          0 :             return "ReturnExpr";
     183                 :          0 :         case NodeTypeDefer:
     184                 :          0 :             return "Defer";
     185                 :          0 :         case NodeTypeVariableDeclaration:
     186                 :          0 :             return "VariableDeclaration";
     187                 :          0 :         case NodeTypeTestDecl:
     188                 :          0 :             return "TestDecl";
     189                 :          0 :         case NodeTypeIntLiteral:
     190                 :          0 :             return "IntLiteral";
     191                 :          0 :         case NodeTypeFloatLiteral:
     192                 :          0 :             return "FloatLiteral";
     193                 :          0 :         case NodeTypeStringLiteral:
     194                 :          0 :             return "StringLiteral";
     195                 :          0 :         case NodeTypeCharLiteral:
     196                 :          0 :             return "CharLiteral";
     197                 :          0 :         case NodeTypeSymbol:
     198                 :          0 :             return "Symbol";
     199                 :          0 :         case NodeTypePrefixOpExpr:
     200                 :          0 :             return "PrefixOpExpr";
     201                 :          0 :         case NodeTypeUsingNamespace:
     202                 :          0 :             return "UsingNamespace";
     203                 :          0 :         case NodeTypeBoolLiteral:
     204                 :          0 :             return "BoolLiteral";
     205                 :          0 :         case NodeTypeNullLiteral:
     206                 :          0 :             return "NullLiteral";
     207                 :          0 :         case NodeTypeUndefinedLiteral:
     208                 :          0 :             return "UndefinedLiteral";
     209                 :          0 :         case NodeTypeIfBoolExpr:
     210                 :          0 :             return "IfBoolExpr";
     211                 :          0 :         case NodeTypeWhileExpr:
     212                 :          0 :             return "WhileExpr";
     213                 :          0 :         case NodeTypeForExpr:
     214                 :          0 :             return "ForExpr";
     215                 :          0 :         case NodeTypeSwitchExpr:
     216                 :          0 :             return "SwitchExpr";
     217                 :          0 :         case NodeTypeSwitchProng:
     218                 :          0 :             return "SwitchProng";
     219                 :          0 :         case NodeTypeSwitchRange:
     220                 :          0 :             return "SwitchRange";
     221                 :          0 :         case NodeTypeCompTime:
     222                 :          0 :             return "CompTime";
     223                 :          0 :         case NodeTypeBreak:
     224                 :          0 :             return "Break";
     225                 :          0 :         case NodeTypeContinue:
     226                 :          0 :             return "Continue";
     227                 :          0 :         case NodeTypeUnreachable:
     228                 :          0 :             return "Unreachable";
     229                 :          0 :         case NodeTypeAsmExpr:
     230                 :          0 :             return "AsmExpr";
     231                 :          0 :         case NodeTypeFieldAccessExpr:
     232                 :          0 :             return "FieldAccessExpr";
     233                 :          0 :         case NodeTypePtrDeref:
     234                 :          0 :             return "PtrDerefExpr";
     235                 :          0 :         case NodeTypeUnwrapOptional:
     236                 :          0 :             return "UnwrapOptional";
     237                 :          0 :         case NodeTypeContainerDecl:
     238                 :          0 :             return "ContainerDecl";
     239                 :          0 :         case NodeTypeStructField:
     240                 :          0 :             return "StructField";
     241                 :          0 :         case NodeTypeStructValueField:
     242                 :          0 :             return "StructValueField";
     243                 :          0 :         case NodeTypeContainerInitExpr:
     244                 :          0 :             return "ContainerInitExpr";
     245                 :          0 :         case NodeTypeArrayType:
     246                 :          0 :             return "ArrayType";
     247                 :          0 :         case NodeTypeInferredArrayType:
     248                 :          0 :             return "InferredArrayType";
     249                 :          0 :         case NodeTypeErrorType:
     250                 :          0 :             return "ErrorType";
     251                 :          0 :         case NodeTypeIfErrorExpr:
     252                 :          0 :             return "IfErrorExpr";
     253                 :          0 :         case NodeTypeIfOptional:
     254                 :          0 :             return "IfOptional";
     255                 :          0 :         case NodeTypeErrorSetDecl:
     256                 :          0 :             return "ErrorSetDecl";
     257                 :          0 :         case NodeTypeResume:
     258                 :          0 :             return "Resume";
     259                 :          0 :         case NodeTypeAwaitExpr:
     260                 :          0 :             return "AwaitExpr";
     261                 :          0 :         case NodeTypeSuspend:
     262                 :          0 :             return "Suspend";
     263                 :          0 :         case NodeTypePointerType:
     264                 :          0 :             return "PointerType";
     265                 :          0 :         case NodeTypeAnyFrameType:
     266                 :          0 :             return "AnyFrameType";
     267                 :          0 :         case NodeTypeEnumLiteral:
     268                 :          0 :             return "EnumLiteral";
     269                 :            :     }
     270                 :          0 :     zig_unreachable();
     271                 :            : }
     272                 :            : 
     273                 :            : struct AstPrint {
     274                 :            :     int indent;
     275                 :            :     FILE *f;
     276                 :            : };
     277                 :            : 
     278                 :          0 : static void ast_print_visit(AstNode **node_ptr, void *context) {
     279                 :          0 :     AstNode *node = *node_ptr;
     280                 :          0 :     AstPrint *ap = (AstPrint *)context;
     281                 :            : 
     282         [ #  # ]:          0 :     for (int i = 0; i < ap->indent; i += 1) {
     283                 :          0 :         fprintf(ap->f, " ");
     284                 :            :     }
     285                 :            : 
     286                 :          0 :     fprintf(ap->f, "%s\n", node_type_str(node->type));
     287                 :            : 
     288                 :            :     AstPrint new_ap;
     289                 :          0 :     new_ap.indent = ap->indent + 2;
     290                 :          0 :     new_ap.f = ap->f;
     291                 :            : 
     292                 :          0 :     ast_visit_node_children(node, ast_print_visit, &new_ap);
     293                 :          0 : }
     294                 :            : 
     295                 :          0 : void ast_print(FILE *f, AstNode *node, int indent) {
     296                 :            :     AstPrint ap;
     297                 :          0 :     ap.indent = indent;
     298                 :          0 :     ap.f = f;
     299                 :          0 :     ast_visit_node_children(node, ast_print_visit, &ap);
     300                 :          0 : }
     301                 :            : 
     302                 :            : 
     303                 :            : struct AstRender {
     304                 :            :     int indent;
     305                 :            :     int indent_size;
     306                 :            :     FILE *f;
     307                 :            : };
     308                 :            : 
     309                 :          0 : static void print_indent(AstRender *ar) {
     310         [ #  # ]:          0 :     for (int i = 0; i < ar->indent; i += 1) {
     311                 :          0 :         fprintf(ar->f, " ");
     312                 :            :     }
     313                 :          0 : }
     314                 :            : 
     315                 :          0 : static bool is_alpha_under(uint8_t c) {
     316 [ #  # ][ #  # ]:          0 :     return (c >= 'a' && c <= 'z') ||
     317 [ #  # ][ #  # ]:          0 :         (c >= 'A' && c <= 'Z') || c == '_';
                 [ #  # ]
     318                 :            : }
     319                 :            : 
     320                 :          0 : static bool is_digit(uint8_t c) {
     321 [ #  # ][ #  # ]:          0 :     return (c >= '0' && c <= '9');
     322                 :            : }
     323                 :            : 
     324                 :          0 : static bool is_printable(uint8_t c) {
     325         [ #  # ]:          0 :     if (c == 0) {
     326                 :          0 :         return false;
     327                 :            :     }
     328                 :            :     static const uint8_t printables[] =
     329                 :            :         " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.~`!@#$%^&*()_-+=\\{}[];'\"?/<>,:";
     330         [ #  # ]:          0 :     for (size_t i = 0; i < array_length(printables); i += 1) {
     331         [ #  # ]:          0 :         if (c == printables[i]) return true;
     332                 :            :     }
     333                 :          0 :     return false;
     334                 :            : }
     335                 :            : 
     336                 :          0 : static void string_literal_escape(Buf *source, Buf *dest) {
     337                 :          0 :     buf_resize(dest, 0);
     338         [ #  # ]:          0 :     for (size_t i = 0; i < buf_len(source); i += 1) {
     339                 :          0 :         uint8_t c = *((uint8_t*)buf_ptr(source) + i);
     340         [ #  # ]:          0 :         if (c == '\'') {
     341                 :          0 :             buf_append_str(dest, "\\'");
     342         [ #  # ]:          0 :         } else if (c == '"') {
     343                 :          0 :             buf_append_str(dest, "\\\"");
     344         [ #  # ]:          0 :         } else if (c == '\\') {
     345                 :          0 :             buf_append_str(dest, "\\\\");
     346         [ #  # ]:          0 :         } else if (c == '\n') {
     347                 :          0 :             buf_append_str(dest, "\\n");
     348         [ #  # ]:          0 :         } else if (c == '\r') {
     349                 :          0 :             buf_append_str(dest, "\\r");
     350         [ #  # ]:          0 :         } else if (c == '\t') {
     351                 :          0 :             buf_append_str(dest, "\\t");
     352         [ #  # ]:          0 :         } else if (is_printable(c)) {
     353                 :          0 :             buf_append_char(dest, c);
     354                 :            :         } else {
     355                 :          0 :             buf_appendf(dest, "\\x%02x", (int)c);
     356                 :            :         }
     357                 :            :     }
     358                 :          0 : }
     359                 :            : 
     360                 :          0 : static bool is_valid_bare_symbol(Buf *symbol) {
     361         [ #  # ]:          0 :     if (buf_len(symbol) == 0) {
     362                 :          0 :         return false;
     363                 :            :     }
     364                 :          0 :     uint8_t first_char = *buf_ptr(symbol);
     365         [ #  # ]:          0 :     if (!is_alpha_under(first_char)) {
     366                 :          0 :         return false;
     367                 :            :     }
     368         [ #  # ]:          0 :     for (size_t i = 1; i < buf_len(symbol); i += 1) {
     369                 :          0 :         uint8_t c = *((uint8_t*)buf_ptr(symbol) + i);
     370 [ #  # ][ #  # ]:          0 :         if (!is_alpha_under(c) && !is_digit(c)) {
                 [ #  # ]
     371                 :          0 :             return false;
     372                 :            :         }
     373                 :            :     }
     374                 :          0 :     return true;
     375                 :            : }
     376                 :            : 
     377                 :          0 : static void print_symbol(AstRender *ar, Buf *symbol) {
     378         [ #  # ]:          0 :     if (is_zig_keyword(symbol)) {
     379                 :          0 :         fprintf(ar->f, "@\"%s\"", buf_ptr(symbol));
     380                 :          0 :         return;
     381                 :            :     }
     382         [ #  # ]:          0 :     if (is_valid_bare_symbol(symbol)) {
     383                 :          0 :         fprintf(ar->f, "%s", buf_ptr(symbol));
     384                 :          0 :         return;
     385                 :            :     }
     386                 :          0 :     Buf escaped = BUF_INIT;
     387                 :          0 :     string_literal_escape(symbol, &escaped);
     388                 :          0 :     fprintf(ar->f, "@\"%s\"", buf_ptr(&escaped));
     389                 :            : }
     390                 :            : 
     391                 :          0 : static bool statement_terminates_without_semicolon(AstNode *node) {
     392   [ #  #  #  #  :          0 :     switch (node->type) {
          #  #  #  #  #  
                      # ]
     393                 :          0 :         case NodeTypeIfBoolExpr:
     394         [ #  # ]:          0 :             if (node->data.if_bool_expr.else_node)
     395                 :          0 :                 return statement_terminates_without_semicolon(node->data.if_bool_expr.else_node);
     396                 :          0 :             return node->data.if_bool_expr.then_block->type == NodeTypeBlock;
     397                 :          0 :         case NodeTypeIfErrorExpr:
     398         [ #  # ]:          0 :             if (node->data.if_err_expr.else_node)
     399                 :          0 :                 return statement_terminates_without_semicolon(node->data.if_err_expr.else_node);
     400                 :          0 :             return node->data.if_err_expr.then_node->type == NodeTypeBlock;
     401                 :          0 :         case NodeTypeIfOptional:
     402         [ #  # ]:          0 :             if (node->data.test_expr.else_node)
     403                 :          0 :                 return statement_terminates_without_semicolon(node->data.test_expr.else_node);
     404                 :          0 :             return node->data.test_expr.then_node->type == NodeTypeBlock;
     405                 :          0 :         case NodeTypeWhileExpr:
     406                 :          0 :             return node->data.while_expr.body->type == NodeTypeBlock;
     407                 :          0 :         case NodeTypeForExpr:
     408                 :          0 :             return node->data.for_expr.body->type == NodeTypeBlock;
     409                 :          0 :         case NodeTypeCompTime:
     410                 :          0 :             return node->data.comptime_expr.expr->type == NodeTypeBlock;
     411                 :          0 :         case NodeTypeDefer:
     412                 :          0 :             return node->data.defer.expr->type == NodeTypeBlock;
     413                 :          0 :         case NodeTypeSuspend:
     414 [ #  # ][ #  # ]:          0 :             return node->data.suspend.block != nullptr && node->data.suspend.block->type == NodeTypeBlock;
     415                 :          0 :         case NodeTypeSwitchExpr:
     416                 :            :         case NodeTypeBlock:
     417                 :          0 :             return true;
     418                 :          0 :         default:
     419                 :          0 :             return false;
     420                 :            :     }
     421                 :            : }
     422                 :            : 
     423                 :            : static void render_node_extra(AstRender *ar, AstNode *node, bool grouped);
     424                 :            : 
     425                 :          0 : static void render_node_grouped(AstRender *ar, AstNode *node) {
     426                 :          0 :     return render_node_extra(ar, node, true);
     427                 :            : }
     428                 :            : 
     429                 :          0 : static void render_node_ungrouped(AstRender *ar, AstNode *node) {
     430                 :          0 :     return render_node_extra(ar, node, false);
     431                 :            : }
     432                 :            : 
     433                 :          0 : static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
     434   [ #  #  #  #  :          0 :     switch (node->type) {
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
     435                 :          0 :         case NodeTypeSwitchProng:
     436                 :            :         case NodeTypeSwitchRange:
     437                 :            :         case NodeTypeStructValueField:
     438                 :          0 :             zig_unreachable();
     439                 :          0 :         case NodeTypeFnProto:
     440                 :            :             {
     441                 :          0 :                 const char *pub_str = visib_mod_string(node->data.fn_proto.visib_mod);
     442                 :          0 :                 const char *extern_str = extern_string(node->data.fn_proto.is_extern);
     443                 :          0 :                 const char *export_str = export_string(node->data.fn_proto.is_export);
     444                 :          0 :                 const char *inline_str = inline_string(node->data.fn_proto.fn_inline);
     445                 :          0 :                 fprintf(ar->f, "%s%s%s%sfn ", pub_str, inline_str, export_str, extern_str);
     446         [ #  # ]:          0 :                 if (node->data.fn_proto.name != nullptr) {
     447                 :          0 :                     print_symbol(ar, node->data.fn_proto.name);
     448                 :            :                 }
     449                 :          0 :                 fprintf(ar->f, "(");
     450                 :          0 :                 size_t arg_count = node->data.fn_proto.params.length;
     451         [ #  # ]:          0 :                 for (size_t arg_i = 0; arg_i < arg_count; arg_i += 1) {
     452                 :          0 :                     AstNode *param_decl = node->data.fn_proto.params.at(arg_i);
     453                 :          0 :                     assert(param_decl->type == NodeTypeParamDecl);
     454         [ #  # ]:          0 :                     if (param_decl->data.param_decl.name != nullptr) {
     455         [ #  # ]:          0 :                         const char *noalias_str = param_decl->data.param_decl.is_noalias ? "noalias " : "";
     456         [ #  # ]:          0 :                         const char *inline_str = param_decl->data.param_decl.is_comptime ? "comptime " : "";
     457                 :          0 :                         fprintf(ar->f, "%s%s", noalias_str, inline_str);
     458                 :          0 :                         print_symbol(ar, param_decl->data.param_decl.name);
     459                 :          0 :                         fprintf(ar->f, ": ");
     460                 :            :                     }
     461         [ #  # ]:          0 :                     if (param_decl->data.param_decl.is_var_args) {
     462                 :          0 :                         fprintf(ar->f, "...");
     463         [ #  # ]:          0 :                     } else if (param_decl->data.param_decl.var_token != nullptr) {
     464                 :          0 :                         fprintf(ar->f, "var");
     465                 :            :                     } else {
     466                 :          0 :                         render_node_grouped(ar, param_decl->data.param_decl.type);
     467                 :            :                     }
     468                 :            : 
     469         [ #  # ]:          0 :                     if (arg_i + 1 < arg_count) {
     470                 :          0 :                         fprintf(ar->f, ", ");
     471                 :            :                     }
     472                 :            :                 }
     473         [ #  # ]:          0 :                 if (node->data.fn_proto.is_var_args) {
     474                 :          0 :                     fprintf(ar->f, ", ...");
     475                 :            :                 }
     476                 :          0 :                 fprintf(ar->f, ")");
     477         [ #  # ]:          0 :                 if (node->data.fn_proto.align_expr) {
     478                 :          0 :                     fprintf(ar->f, " align(");
     479                 :          0 :                     render_node_grouped(ar, node->data.fn_proto.align_expr);
     480                 :          0 :                     fprintf(ar->f, ")");
     481                 :            :                 }
     482         [ #  # ]:          0 :                 if (node->data.fn_proto.section_expr) {
     483                 :          0 :                     fprintf(ar->f, " section(");
     484                 :          0 :                     render_node_grouped(ar, node->data.fn_proto.section_expr);
     485                 :          0 :                     fprintf(ar->f, ")");
     486                 :            :                 }
     487                 :            : 
     488         [ #  # ]:          0 :                 if (node->data.fn_proto.return_var_token != nullptr) {
     489                 :          0 :                     fprintf(ar->f, "var");
     490                 :            :                 } else {
     491                 :          0 :                     AstNode *return_type_node = node->data.fn_proto.return_type;
     492                 :          0 :                     assert(return_type_node != nullptr);
     493                 :          0 :                     fprintf(ar->f, " ");
     494         [ #  # ]:          0 :                     if (node->data.fn_proto.auto_err_set) {
     495                 :          0 :                         fprintf(ar->f, "!");
     496                 :            :                     }
     497                 :          0 :                     render_node_grouped(ar, return_type_node);
     498                 :            :                 }
     499                 :          0 :                 break;
     500                 :            :             }
     501                 :          0 :         case NodeTypeFnDef:
     502                 :            :             {
     503                 :          0 :                 render_node_grouped(ar, node->data.fn_def.fn_proto);
     504                 :          0 :                 fprintf(ar->f, " ");
     505                 :          0 :                 render_node_grouped(ar, node->data.fn_def.body);
     506                 :          0 :                 break;
     507                 :            :             }
     508                 :          0 :         case NodeTypeBlock:
     509         [ #  # ]:          0 :             if (node->data.block.name != nullptr) {
     510                 :          0 :                 fprintf(ar->f, "%s: ", buf_ptr(node->data.block.name));
     511                 :            :             }
     512         [ #  # ]:          0 :             if (node->data.block.statements.length == 0) {
     513                 :          0 :                 fprintf(ar->f, "{}");
     514                 :          0 :                 break;
     515                 :            :             }
     516                 :          0 :             fprintf(ar->f, "{\n");
     517                 :          0 :             ar->indent += ar->indent_size;
     518         [ #  # ]:          0 :             for (size_t i = 0; i < node->data.block.statements.length; i += 1) {
     519                 :          0 :                 AstNode *statement = node->data.block.statements.at(i);
     520                 :          0 :                 print_indent(ar);
     521                 :          0 :                 render_node_grouped(ar, statement);
     522                 :            : 
     523         [ #  # ]:          0 :                 if (!statement_terminates_without_semicolon(statement))
     524                 :          0 :                     fprintf(ar->f, ";");
     525                 :            : 
     526                 :          0 :                 fprintf(ar->f, "\n");
     527                 :            :             }
     528                 :          0 :             ar->indent -= ar->indent_size;
     529                 :          0 :             print_indent(ar);
     530                 :          0 :             fprintf(ar->f, "}");
     531                 :          0 :             break;
     532                 :          0 :         case NodeTypeGroupedExpr:
     533                 :          0 :             fprintf(ar->f, "(");
     534                 :          0 :             render_node_ungrouped(ar, node->data.grouped_expr);
     535                 :          0 :             fprintf(ar->f, ")");
     536                 :          0 :             break;
     537                 :          0 :         case NodeTypeReturnExpr:
     538                 :            :             {
     539                 :          0 :                 const char *return_str = return_string(node->data.return_expr.kind);
     540                 :          0 :                 fprintf(ar->f, "%s", return_str);
     541         [ #  # ]:          0 :                 if (node->data.return_expr.expr) {
     542                 :          0 :                     fprintf(ar->f, " ");
     543                 :          0 :                     render_node_grouped(ar, node->data.return_expr.expr);
     544                 :            :                 }
     545                 :          0 :                 break;
     546                 :            :             }
     547                 :          0 :         case NodeTypeBreak:
     548                 :            :             {
     549                 :          0 :                 fprintf(ar->f, "break");
     550         [ #  # ]:          0 :                 if (node->data.break_expr.name != nullptr) {
     551                 :          0 :                     fprintf(ar->f, " :%s", buf_ptr(node->data.break_expr.name));
     552                 :            :                 }
     553         [ #  # ]:          0 :                 if (node->data.break_expr.expr) {
     554                 :          0 :                     fprintf(ar->f, " ");
     555                 :          0 :                     render_node_grouped(ar, node->data.break_expr.expr);
     556                 :            :                 }
     557                 :          0 :                 break;
     558                 :            :             }
     559                 :          0 :         case NodeTypeDefer:
     560                 :            :             {
     561                 :          0 :                 const char *defer_str = defer_string(node->data.defer.kind);
     562                 :          0 :                 fprintf(ar->f, "%s ", defer_str);
     563                 :          0 :                 render_node_grouped(ar, node->data.return_expr.expr);
     564                 :          0 :                 break;
     565                 :            :             }
     566                 :          0 :         case NodeTypeVariableDeclaration:
     567                 :            :             {
     568                 :          0 :                 const char *pub_str = visib_mod_string(node->data.variable_declaration.visib_mod);
     569                 :          0 :                 const char *extern_str = extern_string(node->data.variable_declaration.is_extern);
     570                 :          0 :                 const char *thread_local_str = thread_local_string(node->data.variable_declaration.threadlocal_tok);
     571                 :          0 :                 const char *const_or_var = const_or_var_string(node->data.variable_declaration.is_const);
     572                 :          0 :                 fprintf(ar->f, "%s%s%s%s ", pub_str, extern_str, thread_local_str, const_or_var);
     573                 :          0 :                 print_symbol(ar, node->data.variable_declaration.symbol);
     574                 :            : 
     575         [ #  # ]:          0 :                 if (node->data.variable_declaration.type) {
     576                 :          0 :                     fprintf(ar->f, ": ");
     577                 :          0 :                     render_node_grouped(ar, node->data.variable_declaration.type);
     578                 :            :                 }
     579         [ #  # ]:          0 :                 if (node->data.variable_declaration.align_expr) {
     580                 :          0 :                     fprintf(ar->f, "align(");
     581                 :          0 :                     render_node_grouped(ar, node->data.variable_declaration.align_expr);
     582                 :          0 :                     fprintf(ar->f, ") ");
     583                 :            :                 }
     584         [ #  # ]:          0 :                 if (node->data.variable_declaration.section_expr) {
     585                 :          0 :                     fprintf(ar->f, "section(");
     586                 :          0 :                     render_node_grouped(ar, node->data.variable_declaration.section_expr);
     587                 :          0 :                     fprintf(ar->f, ") ");
     588                 :            :                 }
     589         [ #  # ]:          0 :                 if (node->data.variable_declaration.expr) {
     590                 :          0 :                     fprintf(ar->f, " = ");
     591                 :          0 :                     render_node_grouped(ar, node->data.variable_declaration.expr);
     592                 :            :                 }
     593                 :          0 :                 break;
     594                 :            :             }
     595                 :          0 :         case NodeTypeBinOpExpr:
     596         [ #  # ]:          0 :             if (!grouped) fprintf(ar->f, "(");
     597                 :          0 :             render_node_ungrouped(ar, node->data.bin_op_expr.op1);
     598                 :          0 :             fprintf(ar->f, " %s ", bin_op_str(node->data.bin_op_expr.bin_op));
     599                 :          0 :             render_node_ungrouped(ar, node->data.bin_op_expr.op2);
     600         [ #  # ]:          0 :             if (!grouped) fprintf(ar->f, ")");
     601                 :          0 :             break;
     602                 :          0 :         case NodeTypeFloatLiteral:
     603                 :            :             {
     604                 :          0 :                 Buf rendered_buf = BUF_INIT;
     605                 :          0 :                 buf_resize(&rendered_buf, 0);
     606                 :          0 :                 bigfloat_append_buf(&rendered_buf, node->data.float_literal.bigfloat);
     607                 :          0 :                 fprintf(ar->f, "%s", buf_ptr(&rendered_buf));
     608                 :            :             }
     609                 :          0 :             break;
     610                 :          0 :         case NodeTypeIntLiteral:
     611                 :            :             {
     612                 :          0 :                 Buf rendered_buf = BUF_INIT;
     613                 :          0 :                 buf_resize(&rendered_buf, 0);
     614                 :          0 :                 bigint_append_buf(&rendered_buf, node->data.int_literal.bigint, 10);
     615                 :          0 :                 fprintf(ar->f, "%s", buf_ptr(&rendered_buf));
     616                 :            :             }
     617                 :          0 :             break;
     618                 :          0 :         case NodeTypeStringLiteral:
     619                 :            :             {
     620         [ #  # ]:          0 :                 if (node->data.string_literal.c) {
     621                 :          0 :                     fprintf(ar->f, "c");
     622                 :            :                 }
     623                 :          0 :                 Buf tmp_buf = BUF_INIT;
     624                 :          0 :                 string_literal_escape(node->data.string_literal.buf, &tmp_buf);
     625                 :          0 :                 fprintf(ar->f, "\"%s\"", buf_ptr(&tmp_buf));
     626                 :            :             }
     627                 :          0 :             break;
     628                 :          0 :         case NodeTypeCharLiteral:
     629                 :            :             {
     630                 :          0 :                 uint8_t c = node->data.char_literal.value;
     631         [ #  # ]:          0 :                 if (c == '\'') {
     632                 :          0 :                     fprintf(ar->f, "'\\''");
     633         [ #  # ]:          0 :                 } else if (c == '\"') {
     634                 :          0 :                     fprintf(ar->f, "'\\\"'");
     635         [ #  # ]:          0 :                 } else if (c == '\\') {
     636                 :          0 :                     fprintf(ar->f, "'\\\\'");
     637         [ #  # ]:          0 :                 } else if (c == '\n') {
     638                 :          0 :                     fprintf(ar->f, "'\\n'");
     639         [ #  # ]:          0 :                 } else if (c == '\r') {
     640                 :          0 :                     fprintf(ar->f, "'\\r'");
     641         [ #  # ]:          0 :                 } else if (c == '\t') {
     642                 :          0 :                     fprintf(ar->f, "'\\t'");
     643         [ #  # ]:          0 :                 } else if (is_printable(c)) {
     644                 :          0 :                     fprintf(ar->f, "'%c'", c);
     645                 :            :                 } else {
     646                 :          0 :                     fprintf(ar->f, "'\\x%02x'", (int)c);
     647                 :            :                 }
     648                 :          0 :                 break;
     649                 :            :             }
     650                 :          0 :         case NodeTypeSymbol:
     651                 :          0 :             print_symbol(ar, node->data.symbol_expr.symbol);
     652                 :          0 :             break;
     653                 :          0 :         case NodeTypePrefixOpExpr:
     654                 :            :             {
     655         [ #  # ]:          0 :                 if (!grouped) fprintf(ar->f, "(");
     656                 :          0 :                 PrefixOp op = node->data.prefix_op_expr.prefix_op;
     657                 :          0 :                 fprintf(ar->f, "%s", prefix_op_str(op));
     658                 :            : 
     659                 :          0 :                 AstNode *child_node = node->data.prefix_op_expr.primary_expr;
     660 [ #  # ][ #  # ]:          0 :                 bool new_grouped = child_node->type == NodeTypePrefixOpExpr || child_node->type == NodeTypePointerType;
     661                 :          0 :                 render_node_extra(ar, child_node, new_grouped);
     662         [ #  # ]:          0 :                 if (!grouped) fprintf(ar->f, ")");
     663                 :          0 :                 break;
     664                 :            :             }
     665                 :          0 :         case NodeTypePointerType:
     666                 :            :             {
     667         [ #  # ]:          0 :                 if (!grouped) fprintf(ar->f, "(");
     668                 :          0 :                 const char *ptr_len_str = token_to_ptr_len_str(node->data.pointer_type.star_token);
     669                 :          0 :                 fprintf(ar->f, "%s", ptr_len_str);
     670         [ #  # ]:          0 :                 if (node->data.pointer_type.align_expr != nullptr) {
     671                 :          0 :                     fprintf(ar->f, "align(");
     672                 :          0 :                     render_node_grouped(ar, node->data.pointer_type.align_expr);
     673         [ #  # ]:          0 :                     if (node->data.pointer_type.bit_offset_start != nullptr) {
     674                 :          0 :                         assert(node->data.pointer_type.host_int_bytes != nullptr);
     675                 :            : 
     676                 :          0 :                         Buf offset_start_buf = BUF_INIT;
     677                 :          0 :                         buf_resize(&offset_start_buf, 0);
     678                 :          0 :                         bigint_append_buf(&offset_start_buf, node->data.pointer_type.bit_offset_start, 10);
     679                 :            : 
     680                 :          0 :                         Buf offset_end_buf = BUF_INIT;
     681                 :          0 :                         buf_resize(&offset_end_buf, 0);
     682                 :          0 :                         bigint_append_buf(&offset_end_buf, node->data.pointer_type.host_int_bytes, 10);
     683                 :            : 
     684                 :          0 :                         fprintf(ar->f, ":%s:%s ", buf_ptr(&offset_start_buf), buf_ptr(&offset_end_buf));
     685                 :            :                     }
     686                 :          0 :                     fprintf(ar->f, ") ");
     687                 :            :                 }
     688         [ #  # ]:          0 :                 if (node->data.pointer_type.is_const) {
     689                 :          0 :                     fprintf(ar->f, "const ");
     690                 :            :                 }
     691         [ #  # ]:          0 :                 if (node->data.pointer_type.is_volatile) {
     692                 :          0 :                     fprintf(ar->f, "volatile ");
     693                 :            :                 }
     694                 :            : 
     695                 :          0 :                 render_node_ungrouped(ar, node->data.pointer_type.op_expr);
     696         [ #  # ]:          0 :                 if (!grouped) fprintf(ar->f, ")");
     697                 :          0 :                 break;
     698                 :            :             }
     699                 :          0 :         case NodeTypeFnCallExpr:
     700                 :            :             {
     701         [ #  # ]:          0 :                 if (node->data.fn_call_expr.is_builtin) {
     702                 :          0 :                     fprintf(ar->f, "@");
     703                 :            :                 }
     704         [ #  # ]:          0 :                 if (node->data.fn_call_expr.is_async) {
     705                 :          0 :                     fprintf(ar->f, "async ");
     706                 :            :                 }
     707                 :          0 :                 AstNode *fn_ref_node = node->data.fn_call_expr.fn_ref_expr;
     708 [ #  # ][ #  # ]:          0 :                 bool grouped = (fn_ref_node->type != NodeTypePrefixOpExpr && fn_ref_node->type != NodeTypePointerType);
     709                 :          0 :                 render_node_extra(ar, fn_ref_node, grouped);
     710                 :          0 :                 fprintf(ar->f, "(");
     711         [ #  # ]:          0 :                 for (size_t i = 0; i < node->data.fn_call_expr.params.length; i += 1) {
     712                 :          0 :                     AstNode *param = node->data.fn_call_expr.params.at(i);
     713         [ #  # ]:          0 :                     if (i != 0) {
     714                 :          0 :                         fprintf(ar->f, ", ");
     715                 :            :                     }
     716                 :          0 :                     render_node_grouped(ar, param);
     717                 :            :                 }
     718                 :          0 :                 fprintf(ar->f, ")");
     719                 :          0 :                 break;
     720                 :            :             }
     721                 :          0 :         case NodeTypeArrayAccessExpr:
     722                 :          0 :             render_node_ungrouped(ar, node->data.array_access_expr.array_ref_expr);
     723                 :          0 :             fprintf(ar->f, "[");
     724                 :          0 :             render_node_grouped(ar, node->data.array_access_expr.subscript);
     725                 :          0 :             fprintf(ar->f, "]");
     726                 :          0 :             break;
     727                 :          0 :         case NodeTypeFieldAccessExpr:
     728                 :            :             {
     729                 :          0 :                 AstNode *lhs = node->data.field_access_expr.struct_expr;
     730                 :          0 :                 Buf *rhs = node->data.field_access_expr.field_name;
     731         [ #  # ]:          0 :                 if (lhs->type == NodeTypeErrorType) {
     732                 :          0 :                     fprintf(ar->f, "error");
     733                 :            :                 } else {
     734                 :          0 :                     render_node_ungrouped(ar, lhs);
     735                 :            :                 }
     736                 :          0 :                 fprintf(ar->f, ".");
     737                 :          0 :                 print_symbol(ar, rhs);
     738                 :          0 :                 break;
     739                 :            :             }
     740                 :          0 :         case NodeTypePtrDeref:
     741                 :            :             {
     742                 :          0 :                 AstNode *lhs = node->data.ptr_deref_expr.target;
     743                 :          0 :                 render_node_ungrouped(ar, lhs);
     744                 :          0 :                 fprintf(ar->f, ".*");
     745                 :          0 :                 break;
     746                 :            :             }
     747                 :          0 :         case NodeTypeUnwrapOptional:
     748                 :            :             {
     749                 :          0 :                 AstNode *lhs = node->data.unwrap_optional.expr;
     750                 :          0 :                 render_node_ungrouped(ar, lhs);
     751                 :          0 :                 fprintf(ar->f, ".?");
     752                 :          0 :                 break;
     753                 :            :             }
     754                 :          0 :         case NodeTypeUndefinedLiteral:
     755                 :          0 :             fprintf(ar->f, "undefined");
     756                 :          0 :             break;
     757                 :          0 :         case NodeTypeContainerDecl:
     758                 :            :             {
     759         [ #  # ]:          0 :                 if (!node->data.container_decl.is_root) {
     760                 :          0 :                     const char *layout_str = layout_string(node->data.container_decl.layout);
     761                 :          0 :                     const char *container_str = container_string(node->data.container_decl.kind);
     762                 :          0 :                     fprintf(ar->f, "%s%s", layout_str, container_str);
     763         [ #  # ]:          0 :                     if (node->data.container_decl.auto_enum) {
     764                 :          0 :                         fprintf(ar->f, "(enum");
     765                 :            :                     }
     766         [ #  # ]:          0 :                     if (node->data.container_decl.init_arg_expr != nullptr) {
     767                 :          0 :                         fprintf(ar->f, "(");
     768                 :          0 :                         render_node_grouped(ar, node->data.container_decl.init_arg_expr);
     769                 :          0 :                         fprintf(ar->f, ")");
     770                 :            :                     }
     771         [ #  # ]:          0 :                     if (node->data.container_decl.auto_enum) {
     772                 :          0 :                         fprintf(ar->f, ")");
     773                 :            :                     }
     774                 :            : 
     775                 :          0 :                     fprintf(ar->f, " {\n");
     776                 :          0 :                     ar->indent += ar->indent_size;
     777                 :            :                 }
     778         [ #  # ]:          0 :                 for (size_t field_i = 0; field_i < node->data.container_decl.fields.length; field_i += 1) {
     779                 :          0 :                     AstNode *field_node = node->data.container_decl.fields.at(field_i);
     780                 :          0 :                     assert(field_node->type == NodeTypeStructField);
     781                 :          0 :                     print_indent(ar);
     782                 :          0 :                     print_symbol(ar, field_node->data.struct_field.name);
     783         [ #  # ]:          0 :                     if (field_node->data.struct_field.type != nullptr) {
     784                 :          0 :                         fprintf(ar->f, ": ");
     785                 :          0 :                         render_node_grouped(ar, field_node->data.struct_field.type);
     786                 :            :                     }
     787         [ #  # ]:          0 :                     if (field_node->data.struct_field.value != nullptr) {
     788                 :          0 :                         fprintf(ar->f, " = ");
     789                 :          0 :                         render_node_grouped(ar, field_node->data.struct_field.value);
     790                 :            :                     }
     791                 :          0 :                     fprintf(ar->f, ",\n");
     792                 :            :                 }
     793                 :            : 
     794         [ #  # ]:          0 :                 for (size_t decl_i = 0; decl_i < node->data.container_decl.decls.length; decl_i += 1) {
     795                 :          0 :                     AstNode *decls_node = node->data.container_decl.decls.at(decl_i);
     796                 :          0 :                     render_node_grouped(ar, decls_node);
     797                 :            : 
     798 [ #  # ][ #  # ]:          0 :                     if (decls_node->type == NodeTypeUsingNamespace ||
     799         [ #  # ]:          0 :                         decls_node->type == NodeTypeVariableDeclaration ||
     800                 :          0 :                         decls_node->type == NodeTypeFnProto)
     801                 :            :                     {
     802                 :          0 :                         fprintf(ar->f, ";");
     803                 :            :                     }
     804                 :          0 :                     fprintf(ar->f, "\n");
     805                 :            :                 }
     806                 :            : 
     807         [ #  # ]:          0 :                 if (!node->data.container_decl.is_root) {
     808                 :          0 :                     ar->indent -= ar->indent_size;
     809                 :          0 :                     print_indent(ar);
     810                 :          0 :                     fprintf(ar->f, "}");
     811                 :            :                 }
     812                 :          0 :                 break;
     813                 :            :             }
     814                 :          0 :         case NodeTypeContainerInitExpr:
     815                 :          0 :             render_node_ungrouped(ar, node->data.container_init_expr.type);
     816         [ #  # ]:          0 :             if (node->data.container_init_expr.kind == ContainerInitKindStruct) {
     817                 :          0 :                 fprintf(ar->f, "{\n");
     818                 :          0 :                 ar->indent += ar->indent_size;
     819                 :            :             } else {
     820                 :          0 :                 fprintf(ar->f, "{");
     821                 :            :             }
     822         [ #  # ]:          0 :             for (size_t i = 0; i < node->data.container_init_expr.entries.length; i += 1) {
     823                 :          0 :                 AstNode *entry = node->data.container_init_expr.entries.at(i);
     824         [ #  # ]:          0 :                 if (entry->type == NodeTypeStructValueField) {
     825                 :          0 :                     Buf *name = entry->data.struct_val_field.name;
     826                 :          0 :                     AstNode *expr = entry->data.struct_val_field.expr;
     827                 :          0 :                     print_indent(ar);
     828                 :          0 :                     fprintf(ar->f, ".%s = ", buf_ptr(name));
     829                 :          0 :                     render_node_grouped(ar, expr);
     830                 :          0 :                     fprintf(ar->f, ",\n");
     831                 :            :                 } else {
     832         [ #  # ]:          0 :                     if (i != 0)
     833                 :          0 :                         fprintf(ar->f, ", ");
     834                 :          0 :                     render_node_grouped(ar, entry);
     835                 :            :                 }
     836                 :            :             }
     837         [ #  # ]:          0 :             if (node->data.container_init_expr.kind == ContainerInitKindStruct) {
     838                 :          0 :                 ar->indent -= ar->indent_size;
     839                 :            :             }
     840                 :          0 :             print_indent(ar);
     841                 :          0 :             fprintf(ar->f, "}");
     842                 :          0 :             break;
     843                 :          0 :         case NodeTypeArrayType:
     844                 :            :             {
     845                 :          0 :                 fprintf(ar->f, "[");
     846         [ #  # ]:          0 :                 if (node->data.array_type.size) {
     847                 :          0 :                     render_node_grouped(ar, node->data.array_type.size);
     848                 :            :                 }
     849                 :          0 :                 fprintf(ar->f, "]");
     850         [ #  # ]:          0 :                 if (node->data.array_type.is_const) {
     851                 :          0 :                     fprintf(ar->f, "const ");
     852                 :            :                 }
     853                 :          0 :                 render_node_ungrouped(ar, node->data.array_type.child_type);
     854                 :          0 :                 break;
     855                 :            :             }
     856                 :          0 :         case NodeTypeInferredArrayType:
     857                 :            :             {
     858                 :          0 :                 fprintf(ar->f, "[_]");
     859                 :          0 :                 render_node_ungrouped(ar, node->data.inferred_array_type.child_type);
     860                 :          0 :                 break;
     861                 :            :             }
     862                 :          0 :         case NodeTypeAnyFrameType: {
     863                 :          0 :             fprintf(ar->f, "anyframe");
     864         [ #  # ]:          0 :             if (node->data.anyframe_type.payload_type != nullptr) {
     865                 :          0 :                 fprintf(ar->f, "->");
     866                 :          0 :                 render_node_grouped(ar, node->data.anyframe_type.payload_type);
     867                 :            :             }
     868                 :          0 :             break;
     869                 :            :         }
     870                 :          0 :         case NodeTypeErrorType:
     871                 :          0 :             fprintf(ar->f, "anyerror");
     872                 :          0 :             break;
     873                 :          0 :         case NodeTypeAsmExpr:
     874                 :            :             {
     875                 :          0 :                 AstNodeAsmExpr *asm_expr = &node->data.asm_expr;
     876         [ #  # ]:          0 :                 const char *volatile_str = (asm_expr->volatile_token != nullptr) ? " volatile" : "";
     877                 :          0 :                 fprintf(ar->f, "asm%s (\"%s\"\n", volatile_str, buf_ptr(&asm_expr->asm_template->data.str_lit.str));
     878                 :          0 :                 print_indent(ar);
     879                 :          0 :                 fprintf(ar->f, ": ");
     880         [ #  # ]:          0 :                 for (size_t i = 0; i < asm_expr->output_list.length; i += 1) {
     881                 :          0 :                     AsmOutput *asm_output = asm_expr->output_list.at(i);
     882                 :            : 
     883         [ #  # ]:          0 :                     if (i != 0) {
     884                 :          0 :                         fprintf(ar->f, ",\n");
     885                 :          0 :                         print_indent(ar);
     886                 :            :                     }
     887                 :            : 
     888                 :          0 :                     fprintf(ar->f, "[%s] \"%s\" (",
     889                 :            :                             buf_ptr(asm_output->asm_symbolic_name),
     890                 :            :                             buf_ptr(asm_output->constraint));
     891         [ #  # ]:          0 :                     if (asm_output->return_type) {
     892                 :          0 :                         fprintf(ar->f, "-> ");
     893                 :          0 :                         render_node_grouped(ar, asm_output->return_type);
     894                 :            :                     } else {
     895                 :          0 :                         fprintf(ar->f, "%s", buf_ptr(asm_output->variable_name));
     896                 :            :                     }
     897                 :          0 :                     fprintf(ar->f, ")");
     898                 :            :                 }
     899                 :          0 :                 fprintf(ar->f, "\n");
     900                 :          0 :                 print_indent(ar);
     901                 :          0 :                 fprintf(ar->f, ": ");
     902         [ #  # ]:          0 :                 for (size_t i = 0; i < asm_expr->input_list.length; i += 1) {
     903                 :          0 :                     AsmInput *asm_input = asm_expr->input_list.at(i);
     904                 :            : 
     905         [ #  # ]:          0 :                     if (i != 0) {
     906                 :          0 :                         fprintf(ar->f, ",\n");
     907                 :          0 :                         print_indent(ar);
     908                 :            :                     }
     909                 :            : 
     910                 :          0 :                     fprintf(ar->f, "[%s] \"%s\" (",
     911                 :            :                             buf_ptr(asm_input->asm_symbolic_name),
     912                 :            :                             buf_ptr(asm_input->constraint));
     913                 :          0 :                     render_node_grouped(ar, asm_input->expr);
     914                 :          0 :                     fprintf(ar->f, ")");
     915                 :            :                 }
     916                 :          0 :                 fprintf(ar->f, "\n");
     917                 :          0 :                 print_indent(ar);
     918                 :          0 :                 fprintf(ar->f, ": ");
     919         [ #  # ]:          0 :                 for (size_t i = 0; i < asm_expr->clobber_list.length; i += 1) {
     920                 :          0 :                     Buf *reg_name = asm_expr->clobber_list.at(i);
     921         [ #  # ]:          0 :                     if (i != 0) fprintf(ar->f, ", ");
     922                 :          0 :                     fprintf(ar->f, "\"%s\"", buf_ptr(reg_name));
     923                 :            :                 }
     924                 :          0 :                 fprintf(ar->f, ")");
     925                 :          0 :                 break;
     926                 :            :             }
     927                 :          0 :         case NodeTypeWhileExpr:
     928                 :            :             {
     929         [ #  # ]:          0 :                 if (node->data.while_expr.name != nullptr) {
     930                 :          0 :                     fprintf(ar->f, "%s: ", buf_ptr(node->data.while_expr.name));
     931                 :            :                 }
     932         [ #  # ]:          0 :                 const char *inline_str = node->data.while_expr.is_inline ? "inline " : "";
     933                 :          0 :                 fprintf(ar->f, "%swhile (", inline_str);
     934                 :          0 :                 render_node_grouped(ar, node->data.while_expr.condition);
     935                 :          0 :                 fprintf(ar->f, ") ");
     936         [ #  # ]:          0 :                 if (node->data.while_expr.var_symbol) {
     937                 :          0 :                     fprintf(ar->f, "|%s| ", buf_ptr(node->data.while_expr.var_symbol));
     938                 :            :                 }
     939         [ #  # ]:          0 :                 if (node->data.while_expr.continue_expr) {
     940                 :          0 :                     fprintf(ar->f, ": (");
     941                 :          0 :                     render_node_grouped(ar, node->data.while_expr.continue_expr);
     942                 :          0 :                     fprintf(ar->f, ") ");
     943                 :            :                 }
     944                 :          0 :                 render_node_grouped(ar, node->data.while_expr.body);
     945         [ #  # ]:          0 :                 if (node->data.while_expr.else_node) {
     946                 :          0 :                     fprintf(ar->f, " else ");
     947         [ #  # ]:          0 :                     if (node->data.while_expr.err_symbol) {
     948                 :          0 :                         fprintf(ar->f, "|%s| ", buf_ptr(node->data.while_expr.err_symbol));
     949                 :            :                     }
     950                 :          0 :                     render_node_grouped(ar, node->data.while_expr.else_node);
     951                 :            :                 }
     952                 :          0 :                 break;
     953                 :            :             }
     954                 :          0 :         case NodeTypeBoolLiteral:
     955                 :            :             {
     956         [ #  # ]:          0 :                 const char *bool_str = node->data.bool_literal.value ? "true" : "false";
     957                 :          0 :                 fprintf(ar->f, "%s", bool_str);
     958                 :          0 :                 break;
     959                 :            :             }
     960                 :          0 :         case NodeTypeIfBoolExpr:
     961                 :            :             {
     962                 :          0 :                 fprintf(ar->f, "if (");
     963                 :          0 :                 render_node_grouped(ar, node->data.if_bool_expr.condition);
     964                 :          0 :                 fprintf(ar->f, ") ");
     965                 :          0 :                 render_node_grouped(ar, node->data.if_bool_expr.then_block);
     966         [ #  # ]:          0 :                 if (node->data.if_bool_expr.else_node) {
     967                 :          0 :                     fprintf(ar->f, " else ");
     968                 :          0 :                     render_node_grouped(ar, node->data.if_bool_expr.else_node);
     969                 :            :                 }
     970                 :          0 :                 break;
     971                 :            :             }
     972                 :          0 :         case NodeTypeNullLiteral:
     973                 :            :             {
     974                 :          0 :                 fprintf(ar->f, "null");
     975                 :          0 :                 break;
     976                 :            :             }
     977                 :          0 :         case NodeTypeIfErrorExpr:
     978                 :            :             {
     979                 :          0 :                 fprintf(ar->f, "if (");
     980                 :          0 :                 render_node_grouped(ar, node->data.if_err_expr.target_node);
     981                 :          0 :                 fprintf(ar->f, ") ");
     982         [ #  # ]:          0 :                 if (node->data.if_err_expr.var_symbol) {
     983         [ #  # ]:          0 :                     const char *ptr_str = node->data.if_err_expr.var_is_ptr ? "*" : "";
     984                 :          0 :                     const char *var_name = buf_ptr(node->data.if_err_expr.var_symbol);
     985                 :          0 :                     fprintf(ar->f, "|%s%s| ", ptr_str, var_name);
     986                 :            :                 }
     987                 :          0 :                 render_node_grouped(ar, node->data.if_err_expr.then_node);
     988         [ #  # ]:          0 :                 if (node->data.if_err_expr.else_node) {
     989                 :          0 :                     fprintf(ar->f, " else ");
     990         [ #  # ]:          0 :                     if (node->data.if_err_expr.err_symbol) {
     991                 :          0 :                         fprintf(ar->f, "|%s| ", buf_ptr(node->data.if_err_expr.err_symbol));
     992                 :            :                     }
     993                 :          0 :                     render_node_grouped(ar, node->data.if_err_expr.else_node);
     994                 :            :                 }
     995                 :          0 :                 break;
     996                 :            :             }
     997                 :          0 :         case NodeTypeIfOptional:
     998                 :            :             {
     999                 :          0 :                 fprintf(ar->f, "if (");
    1000                 :          0 :                 render_node_grouped(ar, node->data.test_expr.target_node);
    1001                 :          0 :                 fprintf(ar->f, ") ");
    1002         [ #  # ]:          0 :                 if (node->data.test_expr.var_symbol) {
    1003         [ #  # ]:          0 :                     const char *ptr_str = node->data.test_expr.var_is_ptr ? "*" : "";
    1004                 :          0 :                     const char *var_name = buf_ptr(node->data.test_expr.var_symbol);
    1005                 :          0 :                     fprintf(ar->f, "|%s%s| ", ptr_str, var_name);
    1006                 :            :                 }
    1007                 :          0 :                 render_node_grouped(ar, node->data.test_expr.then_node);
    1008         [ #  # ]:          0 :                 if (node->data.test_expr.else_node) {
    1009                 :          0 :                     fprintf(ar->f, " else ");
    1010                 :          0 :                     render_node_grouped(ar, node->data.test_expr.else_node);
    1011                 :            :                 }
    1012                 :          0 :                 break;
    1013                 :            :             }
    1014                 :          0 :         case NodeTypeSwitchExpr:
    1015                 :            :             {
    1016                 :          0 :                 AstNodeSwitchExpr *switch_expr = &node->data.switch_expr;
    1017                 :          0 :                 fprintf(ar->f, "switch (");
    1018                 :          0 :                 render_node_grouped(ar, switch_expr->expr);
    1019                 :          0 :                 fprintf(ar->f, ") {\n");
    1020                 :          0 :                 ar->indent += ar->indent_size;
    1021                 :            : 
    1022         [ #  # ]:          0 :                 for (size_t prong_i = 0; prong_i < switch_expr->prongs.length; prong_i += 1) {
    1023                 :          0 :                     AstNode *prong_node = switch_expr->prongs.at(prong_i);
    1024                 :          0 :                     AstNodeSwitchProng *switch_prong = &prong_node->data.switch_prong;
    1025                 :          0 :                     print_indent(ar);
    1026         [ #  # ]:          0 :                     for (size_t item_i = 0; item_i < switch_prong->items.length; item_i += 1) {
    1027                 :          0 :                         AstNode *item_node = switch_prong->items.at(item_i);
    1028         [ #  # ]:          0 :                         if (item_i != 0)
    1029                 :          0 :                             fprintf(ar->f, ", ");
    1030         [ #  # ]:          0 :                         if (item_node->type == NodeTypeSwitchRange) {
    1031                 :          0 :                             AstNode *start_node = item_node->data.switch_range.start;
    1032                 :          0 :                             AstNode *end_node = item_node->data.switch_range.end;
    1033                 :          0 :                             render_node_grouped(ar, start_node);
    1034                 :          0 :                             fprintf(ar->f, "...");
    1035                 :          0 :                             render_node_grouped(ar, end_node);
    1036                 :            :                         } else {
    1037                 :          0 :                             render_node_grouped(ar, item_node);
    1038                 :            :                         }
    1039                 :            :                     }
    1040         [ #  # ]:          0 :                     const char *else_str = (switch_prong->items.length == 0) ? "else" : "";
    1041                 :          0 :                     fprintf(ar->f, "%s => ", else_str);
    1042         [ #  # ]:          0 :                     if (switch_prong->var_symbol) {
    1043         [ #  # ]:          0 :                         const char *star_str = switch_prong->var_is_ptr ? "*" : "";
    1044                 :          0 :                         Buf *var_name = switch_prong->var_symbol->data.symbol_expr.symbol;
    1045                 :          0 :                         fprintf(ar->f, "|%s%s| ", star_str, buf_ptr(var_name));
    1046                 :            :                     }
    1047                 :          0 :                     render_node_grouped(ar, switch_prong->expr);
    1048                 :          0 :                     fprintf(ar->f, ",\n");
    1049                 :            :                 }
    1050                 :            : 
    1051                 :          0 :                 ar->indent -= ar->indent_size;
    1052                 :          0 :                 print_indent(ar);
    1053                 :          0 :                 fprintf(ar->f, "}");
    1054                 :          0 :                 break;
    1055                 :            :             }
    1056                 :          0 :         case NodeTypeCompTime:
    1057                 :            :             {
    1058                 :          0 :                 fprintf(ar->f, "comptime ");
    1059                 :          0 :                 render_node_grouped(ar, node->data.comptime_expr.expr);
    1060                 :          0 :                 break;
    1061                 :            :             }
    1062                 :          0 :         case NodeTypeForExpr:
    1063                 :            :             {
    1064         [ #  # ]:          0 :                 if (node->data.for_expr.name != nullptr) {
    1065                 :          0 :                     fprintf(ar->f, "%s: ", buf_ptr(node->data.for_expr.name));
    1066                 :            :                 }
    1067         [ #  # ]:          0 :                 const char *inline_str = node->data.for_expr.is_inline ? "inline " : "";
    1068                 :          0 :                 fprintf(ar->f, "%sfor (", inline_str);
    1069                 :          0 :                 render_node_grouped(ar, node->data.for_expr.array_expr);
    1070                 :          0 :                 fprintf(ar->f, ") ");
    1071         [ #  # ]:          0 :                 if (node->data.for_expr.elem_node) {
    1072                 :          0 :                     fprintf(ar->f, "|");
    1073         [ #  # ]:          0 :                     if (node->data.for_expr.elem_is_ptr)
    1074                 :          0 :                         fprintf(ar->f, "*");
    1075                 :          0 :                     render_node_grouped(ar, node->data.for_expr.elem_node);
    1076         [ #  # ]:          0 :                     if (node->data.for_expr.index_node) {
    1077                 :          0 :                         fprintf(ar->f, ", ");
    1078                 :          0 :                         render_node_grouped(ar, node->data.for_expr.index_node);
    1079                 :            :                     }
    1080                 :          0 :                     fprintf(ar->f, "| ");
    1081                 :            :                 }
    1082                 :          0 :                 render_node_grouped(ar, node->data.for_expr.body);
    1083         [ #  # ]:          0 :                 if (node->data.for_expr.else_node) {
    1084                 :          0 :                     fprintf(ar->f, " else");
    1085                 :          0 :                     render_node_grouped(ar, node->data.for_expr.else_node);
    1086                 :            :                 }
    1087                 :          0 :                 break;
    1088                 :            :             }
    1089                 :          0 :         case NodeTypeContinue:
    1090                 :            :             {
    1091                 :          0 :                 fprintf(ar->f, "continue");
    1092         [ #  # ]:          0 :                 if (node->data.continue_expr.name != nullptr) {
    1093                 :          0 :                     fprintf(ar->f, " :%s", buf_ptr(node->data.continue_expr.name));
    1094                 :            :                 }
    1095                 :          0 :                 break;
    1096                 :            :             }
    1097                 :          0 :         case NodeTypeUnreachable:
    1098                 :            :             {
    1099                 :          0 :                 fprintf(ar->f, "unreachable");
    1100                 :          0 :                 break;
    1101                 :            :             }
    1102                 :          0 :         case NodeTypeSliceExpr:
    1103                 :            :             {
    1104                 :          0 :                 render_node_ungrouped(ar, node->data.slice_expr.array_ref_expr);
    1105                 :          0 :                 fprintf(ar->f, "[");
    1106                 :          0 :                 render_node_grouped(ar, node->data.slice_expr.start);
    1107                 :          0 :                 fprintf(ar->f, "..");
    1108         [ #  # ]:          0 :                 if (node->data.slice_expr.end)
    1109                 :          0 :                     render_node_grouped(ar, node->data.slice_expr.end);
    1110                 :          0 :                 fprintf(ar->f, "]");
    1111                 :          0 :                 break;
    1112                 :            :             }
    1113                 :          0 :         case NodeTypeCatchExpr:
    1114                 :            :             {
    1115                 :          0 :                 render_node_ungrouped(ar, node->data.unwrap_err_expr.op1);
    1116                 :          0 :                 fprintf(ar->f, " catch ");
    1117         [ #  # ]:          0 :                 if (node->data.unwrap_err_expr.symbol) {
    1118                 :          0 :                     Buf *var_name = node->data.unwrap_err_expr.symbol->data.symbol_expr.symbol;
    1119                 :          0 :                     fprintf(ar->f, "|%s| ", buf_ptr(var_name));
    1120                 :            :                 }
    1121                 :          0 :                 render_node_ungrouped(ar, node->data.unwrap_err_expr.op2);
    1122                 :          0 :                 break;
    1123                 :            :             }
    1124                 :          0 :         case NodeTypeErrorSetDecl:
    1125                 :            :             {
    1126                 :          0 :                 fprintf(ar->f, "error {\n");
    1127                 :          0 :                 ar->indent += ar->indent_size;
    1128                 :            : 
    1129         [ #  # ]:          0 :                 for (size_t i = 0; i < node->data.err_set_decl.decls.length; i += 1) {
    1130                 :          0 :                     AstNode *field_node = node->data.err_set_decl.decls.at(i);
    1131                 :          0 :                     assert(field_node->type == NodeTypeSymbol);
    1132                 :          0 :                     print_indent(ar);
    1133                 :          0 :                     print_symbol(ar, field_node->data.symbol_expr.symbol);
    1134                 :          0 :                     fprintf(ar->f, ",\n");
    1135                 :            :                 }
    1136                 :            : 
    1137                 :          0 :                 ar->indent -= ar->indent_size;
    1138                 :          0 :                 print_indent(ar);
    1139                 :          0 :                 fprintf(ar->f, "}");
    1140                 :          0 :                 break;
    1141                 :            :             }
    1142                 :          0 :         case NodeTypeResume:
    1143                 :            :             {
    1144                 :          0 :                 fprintf(ar->f, "resume ");
    1145                 :          0 :                 render_node_grouped(ar, node->data.resume_expr.expr);
    1146                 :          0 :                 break;
    1147                 :            :             }
    1148                 :          0 :         case NodeTypeAwaitExpr:
    1149                 :            :             {
    1150                 :          0 :                 fprintf(ar->f, "await ");
    1151                 :          0 :                 render_node_grouped(ar, node->data.await_expr.expr);
    1152                 :          0 :                 break;
    1153                 :            :             }
    1154                 :          0 :         case NodeTypeSuspend:
    1155                 :            :             {
    1156         [ #  # ]:          0 :                 if (node->data.suspend.block != nullptr) {
    1157                 :          0 :                     fprintf(ar->f, "suspend ");
    1158                 :          0 :                     render_node_grouped(ar, node->data.suspend.block);
    1159                 :            :                 } else {
    1160                 :          0 :                     fprintf(ar->f, "suspend\n");
    1161                 :            :                 }
    1162                 :          0 :                 break;
    1163                 :            :             }
    1164                 :          0 :         case NodeTypeEnumLiteral:
    1165                 :            :             {
    1166                 :          0 :                 fprintf(ar->f, ".%s", buf_ptr(&node->data.enum_literal.identifier->data.str_lit.str));
    1167                 :          0 :                 break;
    1168                 :            :             }
    1169                 :          0 :         case NodeTypeParamDecl:
    1170                 :            :         case NodeTypeTestDecl:
    1171                 :            :         case NodeTypeStructField:
    1172                 :            :         case NodeTypeUsingNamespace:
    1173                 :          0 :             zig_panic("TODO more ast rendering");
    1174                 :            :     }
    1175                 :          0 : }
    1176                 :            : 
    1177                 :            : 
    1178                 :          0 : void ast_render(FILE *f, AstNode *node, int indent_size) {
    1179                 :          0 :     AstRender ar = {0};
    1180                 :          0 :     ar.f = f;
    1181                 :          0 :     ar.indent_size = indent_size;
    1182                 :          0 :     ar.indent = 0;
    1183                 :            : 
    1184                 :          0 :     render_node_grouped(&ar, node);
    1185                 :          0 : }
    1186                 :            : 
    1187                 :          0 : void AstNode::src() {
    1188                 :          0 :     fprintf(stderr, "%s:%" ZIG_PRI_usize ":%" ZIG_PRI_usize "\n",
    1189                 :          0 :             buf_ptr(this->owner->data.structure.root_struct->path),
    1190                 :          0 :             this->line + 1, this->column + 1);
    1191                 :          0 : }

Generated by: LCOV version 1.14