| ... | ... | @@ -77,22 +77,11 @@ fn renderExtraNewline(ais: *Ais, tree: ast.Tree, node: ast.Node.Index) Error!voi |
| 77 | 77 | } |
| 78 | 78 | |
| 79 | 79 | fn renderExtraNewlineToken(ais: *Ais, tree: ast.Tree, first_token: ast.TokenIndex) Error!void { |
| 80 | | @panic("TODO implement renderExtraNewlineToken"); |
| 81 | | //var prev_token = first_token; |
| 82 | | //if (prev_token == 0) return; |
| 83 | | //const token_tags = tree.tokens.items(.tag); |
| 84 | | //var newline_threshold: usize = 2; |
| 85 | | //while (token_tags[prev_token - 1] == .DocComment) { |
| 86 | | // if (tree.tokenLocation(tree.token_locs[prev_token - 1].end, prev_token).line == 1) { |
| 87 | | // newline_threshold += 1; |
| 88 | | // } |
| 89 | | // prev_token -= 1; |
| 90 | | //} |
| 91 | | //const prev_token_end = tree.token_locs[prev_token - 1].end; |
| 92 | | //const loc = tree.tokenLocation(prev_token_end, first_token); |
| 93 | | //if (loc.line >= newline_threshold) { |
| 94 | | // try ais.insertNewline(); |
| 95 | | //} |
| 80 | if (first_token == 0) return; |
| 81 | const token_starts = tree.tokens.items(.start); |
| 82 | if (tree.tokenLocation(token_starts[first_token - 1], first_token).line >= 2) { |
| 83 | return ais.insertNewline(); |
| 84 | } |
| 96 | 85 | } |
| 97 | 86 | |
| 98 | 87 | fn renderContainerDecl(ais: *Ais, tree: ast.Tree, decl: ast.Node.Index, space: Space) Error!void { |
| ... | ... | @@ -101,24 +90,43 @@ fn renderContainerDecl(ais: *Ais, tree: ast.Tree, decl: ast.Node.Index, space: S |
| 101 | 90 | const datas = tree.nodes.items(.data); |
| 102 | 91 | try renderDocComments(ais, tree, tree.firstToken(decl)); |
| 103 | 92 | switch (tree.nodes.items(.tag)[decl]) { |
| 104 | | .FnProtoSimple => unreachable, // TODO |
| 105 | | .FnProtoSimpleMulti => unreachable, // TODO |
| 106 | | .FnProtoOne => unreachable, // TODO |
| 107 | | .FnDecl => unreachable, // TODO |
| 108 | | .FnProto => unreachable, // TODO |
| 109 | | // .FnProto => { |
| 110 | | // const fn_proto = @fieldParentPtr(ast.Node.FnProto, "base", decl); |
| 111 | | |
| 112 | | // try renderDocComments(ais, tree, fn_proto, fn_proto.getDocComments()); |
| 113 | | |
| 114 | | // if (fn_proto.getBodyNode()) |body_node| { |
| 115 | | // try renderExpression(ais, tree, decl, .Space); |
| 116 | | // try renderExpression(ais, tree, body_node, space); |
| 117 | | // } else { |
| 118 | | // try renderExpression(ais, tree, decl, .None); |
| 119 | | // try renderToken(ais, tree, tree.nextToken(decl.lastToken()), space); |
| 120 | | // } |
| 121 | | // }, |
| 93 | .FnDecl => { |
| 94 | // Some examples: |
| 95 | // pub extern "foo" fn ... |
| 96 | // export fn ... |
| 97 | const fn_proto = datas[decl].lhs; |
| 98 | const fn_token = main_tokens[fn_proto]; |
| 99 | // Go back to the first token we should render here. |
| 100 | var i = fn_token; |
| 101 | while (i > 0) { |
| 102 | i -= 1; |
| 103 | switch (token_tags[i]) { |
| 104 | .Keyword_extern, |
| 105 | .Keyword_export, |
| 106 | .Keyword_pub, |
| 107 | .StringLiteral, |
| 108 | => continue, |
| 109 | |
| 110 | else => { |
| 111 | i += 1; |
| 112 | break; |
| 113 | }, |
| 114 | } |
| 115 | } |
| 116 | while (i < fn_token) : (i += 1) { |
| 117 | try renderToken(ais, tree, i, .Space); |
| 118 | } |
| 119 | try renderExpression(ais, tree, fn_proto, .Space); |
| 120 | return renderExpression(ais, tree, datas[decl].rhs, space); |
| 121 | }, |
| 122 | .FnProtoSimple, |
| 123 | .FnProtoMulti, |
| 124 | .FnProtoOne, |
| 125 | .FnProto, |
| 126 | => { |
| 127 | try renderExpression(ais, tree, decl, .None); |
| 128 | try renderToken(ais, tree, tree.lastToken(decl) + 1, space); // semicolon |
| 129 | }, |
| 122 | 130 | |
| 123 | 131 | .UsingNamespace => unreachable, // TODO |
| 124 | 132 | // .Use => { |
| ... | ... | @@ -186,90 +194,48 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac |
| 186 | 194 | // } |
| 187 | 195 | // return renderToken(ais, tree, any_type.token, space); |
| 188 | 196 | //}, |
| 197 | .BlockTwo => { |
| 198 | var statements = [2]ast.Node.Index{ datas[node].lhs, datas[node].rhs }; |
| 199 | if (datas[node].lhs == 0) { |
| 200 | return renderBlock(ais, tree, main_tokens[node], statements[0..0], space); |
| 201 | } else if (datas[node].rhs == 0) { |
| 202 | return renderBlock(ais, tree, main_tokens[node], statements[0..1], space); |
| 203 | } else { |
| 204 | return renderBlock(ais, tree, main_tokens[node], statements[0..2], space); |
| 205 | } |
| 206 | }, |
| 189 | 207 | .Block => { |
| 190 | 208 | const lbrace = main_tokens[node]; |
| 191 | | if (token_tags[lbrace - 1] == .Colon and |
| 192 | | token_tags[lbrace - 2] == .Identifier) |
| 193 | | { |
| 194 | | try renderToken(ais, tree, lbrace - 2, .None); |
| 195 | | try renderToken(ais, tree, lbrace - 1, .Space); |
| 196 | | } |
| 197 | | const nodes_data = tree.nodes.items(.data); |
| 198 | | const statements = tree.extra_data[nodes_data[node].lhs..nodes_data[node].rhs]; |
| 209 | const statements = tree.extra_data[datas[node].lhs..datas[node].rhs]; |
| 210 | return renderBlock(ais, tree, main_tokens[node], statements, space); |
| 211 | }, |
| 199 | 212 | |
| 200 | | if (statements.len == 0) { |
| 201 | | ais.pushIndentNextLine(); |
| 202 | | try renderToken(ais, tree, lbrace, .None); |
| 203 | | ais.popIndent(); |
| 204 | | const rbrace = lbrace + 1; |
| 205 | | return renderToken(ais, tree, rbrace, space); |
| 206 | | } else { |
| 207 | | ais.pushIndentNextLine(); |
| 208 | | |
| 209 | | try renderToken(ais, tree, lbrace, .Newline); |
| 210 | | |
| 211 | | for (statements) |stmt, i| { |
| 212 | | switch (node_tags[stmt]) { |
| 213 | | .GlobalVarDecl => try renderVarDecl(ais, tree, tree.globalVarDecl(stmt)), |
| 214 | | .LocalVarDecl => try renderVarDecl(ais, tree, tree.localVarDecl(stmt)), |
| 215 | | .SimpleVarDecl => try renderVarDecl(ais, tree, tree.simpleVarDecl(stmt)), |
| 216 | | .AlignedVarDecl => try renderVarDecl(ais, tree, tree.alignedVarDecl(stmt)), |
| 217 | | else => { |
| 218 | | const semicolon = tree.lastToken(stmt) + 1; |
| 219 | | if (token_tags[semicolon] == .Semicolon) { |
| 220 | | try renderExpression(ais, tree, stmt, .None); |
| 221 | | try renderToken(ais, tree, semicolon, .Newline); |
| 222 | | } else { |
| 223 | | try renderExpression(ais, tree, stmt, .Newline); |
| 224 | | } |
| 225 | | }, |
| 226 | | } |
| 213 | .ErrDefer => { |
| 214 | const defer_token = main_tokens[node]; |
| 215 | const payload_token = datas[node].lhs; |
| 216 | const expr = datas[node].rhs; |
| 227 | 217 | |
| 228 | | if (i + 1 < statements.len) { |
| 229 | | try renderExtraNewline(ais, tree, statements[i + 1]); |
| 230 | | } |
| 231 | | } |
| 232 | | ais.popIndent(); |
| 233 | | // The rbrace could be +1 or +2 from the last token of the last |
| 234 | | // statement in the block because lastToken() does not count semicolons. |
| 235 | | const maybe_rbrace = tree.lastToken(statements[statements.len - 1]) + 1; |
| 236 | | if (token_tags[maybe_rbrace] == .RBrace) { |
| 237 | | return renderToken(ais, tree, maybe_rbrace, space); |
| 238 | | } else { |
| 239 | | assert(token_tags[maybe_rbrace + 1] == .RBrace); |
| 240 | | return renderToken(ais, tree, maybe_rbrace + 1, space); |
| 241 | | } |
| 218 | try renderToken(ais, tree, defer_token, .Space); |
| 219 | if (payload_token != 0) { |
| 220 | try renderToken(ais, tree, payload_token - 1, .None); // | |
| 221 | try renderToken(ais, tree, payload_token, .None); // identifier |
| 222 | try renderToken(ais, tree, payload_token + 1, .Space); // | |
| 242 | 223 | } |
| 224 | return renderExpression(ais, tree, expr, space); |
| 243 | 225 | }, |
| 244 | 226 | |
| 245 | | .Defer => unreachable, // TODO |
| 246 | | .ErrDefer => unreachable, // TODO |
| 247 | | //.Defer => { |
| 248 | | // const defer_node = @fieldParentPtr(ast.Node.Defer, "base", base); |
| 249 | | |
| 250 | | // try renderToken(ais, tree, defer_node.defer_token, Space.Space); |
| 251 | | // if (defer_node.payload) |payload| { |
| 252 | | // try renderExpression(ais, tree, payload, Space.Space); |
| 253 | | // } |
| 254 | | // return renderExpression(ais, tree, defer_node.expr, space); |
| 255 | | //}, |
| 256 | | .Comptime => { |
| 227 | .Defer => { |
| 228 | const defer_token = main_tokens[node]; |
| 229 | const expr = datas[node].rhs; |
| 230 | try renderToken(ais, tree, defer_token, .Space); |
| 231 | return renderExpression(ais, tree, expr, space); |
| 232 | }, |
| 233 | .Comptime, .Nosuspend => { |
| 257 | 234 | const comptime_token = main_tokens[node]; |
| 258 | 235 | const block = datas[node].lhs; |
| 259 | 236 | try renderToken(ais, tree, comptime_token, .Space); |
| 260 | 237 | return renderExpression(ais, tree, block, space); |
| 261 | 238 | }, |
| 262 | | .Nosuspend => unreachable, // TODO |
| 263 | | //.Nosuspend => { |
| 264 | | // const nosuspend_node = @fieldParentPtr(ast.Node.Nosuspend, "base", base); |
| 265 | | // if (mem.eql(u8, tree.tokenSlice(nosuspend_node.nosuspend_token), "noasync")) { |
| 266 | | // // TODO: remove this |
| 267 | | // try ais.writer().writeAll("nosuspend "); |
| 268 | | // } else { |
| 269 | | // try renderToken(ais, tree, nosuspend_node.nosuspend_token, Space.Space); |
| 270 | | // } |
| 271 | | // return renderExpression(ais, tree, nosuspend_node.expr, space); |
| 272 | | //}, |
| 273 | 239 | |
| 274 | 240 | .Suspend => unreachable, // TODO |
| 275 | 241 | //.Suspend => { |
| ... | ... | @@ -1274,140 +1240,16 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac |
| 1274 | 1240 | return renderBuiltinCall(ais, tree, main_tokens[node], params, space); |
| 1275 | 1241 | }, |
| 1276 | 1242 | |
| 1277 | | .FnProtoSimple => unreachable, // TODO |
| 1278 | | .FnProtoSimpleMulti => unreachable, // TODO |
| 1279 | | .FnProtoOne => unreachable, // TODO |
| 1280 | | .FnProto => unreachable, // TODO |
| 1281 | | //.FnProto => { |
| 1282 | | // const fn_proto = @fieldParentPtr(ast.Node.FnProto, "base", base); |
| 1283 | | |
| 1284 | | // if (fn_proto.getVisibToken()) |visib_token_index| { |
| 1285 | | // const visib_token = tree.token_tags[visib_token_index]; |
| 1286 | | // assert(visib_token == .Keyword_pub or visib_token == .Keyword_export); |
| 1287 | | |
| 1288 | | // try renderToken(ais, tree, visib_token_index, Space.Space); // pub |
| 1289 | | // } |
| 1290 | | |
| 1291 | | // if (fn_proto.getExternExportInlineToken()) |extern_export_inline_token| { |
| 1292 | | // if (fn_proto.getIsExternPrototype() == null) |
| 1293 | | // try renderToken(ais, tree, extern_export_inline_token, Space.Space); // extern/export/inline |
| 1294 | | // } |
| 1295 | | |
| 1296 | | // if (fn_proto.getLibName()) |lib_name| { |
| 1297 | | // try renderExpression(ais, tree, lib_name, Space.Space); |
| 1298 | | // } |
| 1299 | | |
| 1300 | | // const lparen = if (fn_proto.getNameToken()) |name_token| blk: { |
| 1301 | | // try renderToken(ais, tree, fn_proto.fn_token, Space.Space); // fn |
| 1302 | | // try renderToken(ais, tree, name_token, Space.None); // name |
| 1303 | | // break :blk tree.nextToken(name_token); |
| 1304 | | // } else blk: { |
| 1305 | | // try renderToken(ais, tree, fn_proto.fn_token, Space.Space); // fn |
| 1306 | | // break :blk tree.nextToken(fn_proto.fn_token); |
| 1307 | | // }; |
| 1308 | | // assert(tree.token_tags[lparen] == .LParen); |
| 1309 | | |
| 1310 | | // const rparen = tree.prevToken( |
| 1311 | | // // the first token for the annotation expressions is the left |
| 1312 | | // // parenthesis, hence the need for two prevToken |
| 1313 | | // if (fn_proto.getAlignExpr()) |align_expr| |
| 1314 | | // tree.prevToken(tree.prevToken(align_expr.firstToken())) |
| 1315 | | // else if (fn_proto.getSectionExpr()) |section_expr| |
| 1316 | | // tree.prevToken(tree.prevToken(section_expr.firstToken())) |
| 1317 | | // else if (fn_proto.getCallconvExpr()) |callconv_expr| |
| 1318 | | // tree.prevToken(tree.prevToken(callconv_expr.firstToken())) |
| 1319 | | // else switch (fn_proto.return_type) { |
| 1320 | | // .Explicit => |node| node.firstToken(), |
| 1321 | | // .InferErrorSet => |node| tree.prevToken(node.firstToken()), |
| 1322 | | // .Invalid => unreachable, |
| 1323 | | // }, |
| 1324 | | // ); |
| 1325 | | // assert(tree.token_tags[rparen] == .RParen); |
| 1326 | | |
| 1327 | | // const src_params_trailing_comma = blk: { |
| 1328 | | // const maybe_comma = tree.token_tags[rparen - 1]; |
| 1329 | | // break :blk maybe_comma == .Comma or maybe_comma == .LineComment; |
| 1330 | | // }; |
| 1331 | | |
| 1332 | | // if (!src_params_trailing_comma) { |
| 1333 | | // try renderToken(ais, tree, lparen, Space.None); // ( |
| 1334 | | |
| 1335 | | // // render all on one line, no trailing comma |
| 1336 | | // for (fn_proto.params()) |param_decl, i| { |
| 1337 | | // try renderParamDecl(allocator, ais, tree, param_decl, Space.None); |
| 1338 | | |
| 1339 | | // if (i + 1 < fn_proto.params_len or fn_proto.getVarArgsToken() != null) { |
| 1340 | | // const comma = tree.nextToken(param_decl.lastToken()); |
| 1341 | | // try renderToken(ais, tree, comma, Space.Space); // , |
| 1342 | | // } |
| 1343 | | // } |
| 1344 | | // if (fn_proto.getVarArgsToken()) |var_args_token| { |
| 1345 | | // try renderToken(ais, tree, var_args_token, Space.None); |
| 1346 | | // } |
| 1347 | | // } else { |
| 1348 | | // // one param per line |
| 1349 | | // ais.pushIndent(); |
| 1350 | | // defer ais.popIndent(); |
| 1351 | | // try renderToken(ais, tree, lparen, Space.Newline); // ( |
| 1352 | | |
| 1353 | | // for (fn_proto.params()) |param_decl| { |
| 1354 | | // try renderParamDecl(allocator, ais, tree, param_decl, Space.Comma); |
| 1355 | | // } |
| 1356 | | // if (fn_proto.getVarArgsToken()) |var_args_token| { |
| 1357 | | // try renderToken(ais, tree, var_args_token, Space.Comma); |
| 1358 | | // } |
| 1359 | | // } |
| 1360 | | |
| 1361 | | // try renderToken(ais, tree, rparen, Space.Space); // ) |
| 1362 | | |
| 1363 | | // if (fn_proto.getAlignExpr()) |align_expr| { |
| 1364 | | // const align_rparen = tree.nextToken(align_expr.lastToken()); |
| 1365 | | // const align_lparen = tree.prevToken(align_expr.firstToken()); |
| 1366 | | // const align_kw = tree.prevToken(align_lparen); |
| 1367 | | |
| 1368 | | // try renderToken(ais, tree, align_kw, Space.None); // align |
| 1369 | | // try renderToken(ais, tree, align_lparen, Space.None); // ( |
| 1370 | | // try renderExpression(ais, tree, align_expr, Space.None); |
| 1371 | | // try renderToken(ais, tree, align_rparen, Space.Space); // ) |
| 1372 | | // } |
| 1373 | | |
| 1374 | | // if (fn_proto.getSectionExpr()) |section_expr| { |
| 1375 | | // const section_rparen = tree.nextToken(section_expr.lastToken()); |
| 1376 | | // const section_lparen = tree.prevToken(section_expr.firstToken()); |
| 1377 | | // const section_kw = tree.prevToken(section_lparen); |
| 1378 | | |
| 1379 | | // try renderToken(ais, tree, section_kw, Space.None); // section |
| 1380 | | // try renderToken(ais, tree, section_lparen, Space.None); // ( |
| 1381 | | // try renderExpression(ais, tree, section_expr, Space.None); |
| 1382 | | // try renderToken(ais, tree, section_rparen, Space.Space); // ) |
| 1383 | | // } |
| 1384 | | |
| 1385 | | // if (fn_proto.getCallconvExpr()) |callconv_expr| { |
| 1386 | | // const callconv_rparen = tree.nextToken(callconv_expr.lastToken()); |
| 1387 | | // const callconv_lparen = tree.prevToken(callconv_expr.firstToken()); |
| 1388 | | // const callconv_kw = tree.prevToken(callconv_lparen); |
| 1389 | | |
| 1390 | | // try renderToken(ais, tree, callconv_kw, Space.None); // callconv |
| 1391 | | // try renderToken(ais, tree, callconv_lparen, Space.None); // ( |
| 1392 | | // try renderExpression(ais, tree, callconv_expr, Space.None); |
| 1393 | | // try renderToken(ais, tree, callconv_rparen, Space.Space); // ) |
| 1394 | | // } else if (fn_proto.getIsExternPrototype() != null) { |
| 1395 | | // try ais.writer().writeAll("callconv(.C) "); |
| 1396 | | // } else if (fn_proto.getIsAsync() != null) { |
| 1397 | | // try ais.writer().writeAll("callconv(.Async) "); |
| 1398 | | // } |
| 1399 | | |
| 1400 | | // switch (fn_proto.return_type) { |
| 1401 | | // .Explicit => |node| { |
| 1402 | | // return renderExpression(ais, tree, node, space); |
| 1403 | | // }, |
| 1404 | | // .InferErrorSet => |node| { |
| 1405 | | // try renderToken(ais, tree, tree.prevToken(node.firstToken()), Space.None); // ! |
| 1406 | | // return renderExpression(ais, tree, node, space); |
| 1407 | | // }, |
| 1408 | | // .Invalid => unreachable, |
| 1409 | | // } |
| 1410 | | //}, |
| 1243 | .FnProtoSimple => { |
| 1244 | var params: [1]ast.Node.Index = undefined; |
| 1245 | return renderFnProto(ais, tree, tree.fnProtoSimple(&params, node), space); |
| 1246 | }, |
| 1247 | .FnProtoMulti => return renderFnProto(ais, tree, tree.fnProtoMulti(node), space), |
| 1248 | .FnProtoOne => { |
| 1249 | var params: [1]ast.Node.Index = undefined; |
| 1250 | return renderFnProto(ais, tree, tree.fnProtoOne(&params, node), space); |
| 1251 | }, |
| 1252 | .FnProto => return renderFnProto(ais, tree, tree.fnProto(node), space), |
| 1411 | 1253 | |
| 1412 | 1254 | .AnyFrameType => unreachable, // TODO |
| 1413 | 1255 | //.AnyFrameType => { |
| ... | ... | @@ -2130,30 +1972,6 @@ fn renderContainerField( |
| 2130 | 1972 | return renderExpressionComma(ais, tree, field.ast.value_expr, space); // value |
| 2131 | 1973 | } |
| 2132 | 1974 | |
| 2133 | | fn renderParamDecl( |
| 2134 | | allocator: *mem.Allocator, |
| 2135 | | ais: *Ais, |
| 2136 | | tree: ast.Tree, |
| 2137 | | param_decl: ast.Node.FnProto.ParamDecl, |
| 2138 | | space: Space, |
| 2139 | | ) Error!void { |
| 2140 | | try renderDocComments(ais, tree, param_decl, param_decl.doc_comments); |
| 2141 | | |
| 2142 | | if (param_decl.comptime_token) |comptime_token| { |
| 2143 | | try renderToken(ais, tree, comptime_token, Space.Space); |
| 2144 | | } |
| 2145 | | if (param_decl.noalias_token) |noalias_token| { |
| 2146 | | try renderToken(ais, tree, noalias_token, Space.Space); |
| 2147 | | } |
| 2148 | | if (param_decl.name_token) |name_token| { |
| 2149 | | try renderToken(ais, tree, name_token, Space.None); |
| 2150 | | try renderToken(ais, tree, tree.nextToken(name_token), Space.Space); // : |
| 2151 | | } |
| 2152 | | switch (param_decl.param_type) { |
| 2153 | | .any_type, .type_expr => |node| try renderExpression(ais, tree, node, space), |
| 2154 | | } |
| 2155 | | } |
| 2156 | | |
| 2157 | 1975 | fn renderBuiltinCall( |
| 2158 | 1976 | ais: *Ais, |
| 2159 | 1977 | tree: ast.Tree, |
| ... | ... | @@ -2200,6 +2018,239 @@ fn renderBuiltinCall( |
| 2200 | 2018 | } |
| 2201 | 2019 | } |
| 2202 | 2020 | |
| 2021 | fn renderFnProto(ais: *Ais, tree: ast.Tree, fn_proto: ast.Full.FnProto, space: Space) Error!void { |
| 2022 | const token_tags = tree.tokens.items(.tag); |
| 2023 | |
| 2024 | const after_fn_token = fn_proto.ast.fn_token + 1; |
| 2025 | const lparen = if (token_tags[after_fn_token] == .Identifier) blk: { |
| 2026 | try renderToken(ais, tree, fn_proto.ast.fn_token, .Space); // fn |
| 2027 | try renderToken(ais, tree, after_fn_token, .None); // name |
| 2028 | break :blk after_fn_token + 1; |
| 2029 | } else blk: { |
| 2030 | try renderToken(ais, tree, fn_proto.ast.fn_token, .Space); // fn |
| 2031 | break :blk fn_proto.ast.fn_token + 1; |
| 2032 | }; |
| 2033 | assert(token_tags[lparen] == .LParen); |
| 2034 | |
| 2035 | const maybe_bang = tree.firstToken(fn_proto.ast.return_type) - 1; |
| 2036 | const rparen = blk: { |
| 2037 | // The first token for the annotation expressions is the left |
| 2038 | // parenthesis, hence the need for two previous tokens. |
| 2039 | if (fn_proto.ast.align_expr != 0) { |
| 2040 | break :blk tree.firstToken(fn_proto.ast.align_expr) - 3; |
| 2041 | } |
| 2042 | if (fn_proto.ast.section_expr != 0) { |
| 2043 | break :blk tree.firstToken(fn_proto.ast.section_expr) - 3; |
| 2044 | } |
| 2045 | if (fn_proto.ast.callconv_expr != 0) { |
| 2046 | break :blk tree.firstToken(fn_proto.ast.callconv_expr) - 3; |
| 2047 | } |
| 2048 | if (token_tags[maybe_bang] == .Bang) { |
| 2049 | break :blk maybe_bang - 1; |
| 2050 | } |
| 2051 | break :blk maybe_bang; |
| 2052 | }; |
| 2053 | assert(token_tags[rparen] == .RParen); |
| 2054 | |
| 2055 | // The params list is a sparse set that does *not* include anytype or ... parameters. |
| 2056 | |
| 2057 | if (token_tags[rparen - 1] != .Comma) { |
| 2058 | // Render all on one line, no trailing comma. |
| 2059 | try renderToken(ais, tree, lparen, .None); // ( |
| 2060 | |
| 2061 | var param_i: usize = 0; |
| 2062 | var last_param_token = lparen; |
| 2063 | while (true) { |
| 2064 | last_param_token += 1; |
| 2065 | switch (token_tags[last_param_token]) { |
| 2066 | .DocComment => { |
| 2067 | try renderToken(ais, tree, last_param_token, .Newline); |
| 2068 | continue; |
| 2069 | }, |
| 2070 | .Ellipsis3 => { |
| 2071 | try renderToken(ais, tree, last_param_token, .None); // ... |
| 2072 | break; |
| 2073 | }, |
| 2074 | .Keyword_noalias, .Keyword_comptime => { |
| 2075 | try renderToken(ais, tree, last_param_token, .Space); |
| 2076 | last_param_token += 1; |
| 2077 | }, |
| 2078 | .Identifier => {}, |
| 2079 | .Keyword_anytype => { |
| 2080 | try renderToken(ais, tree, last_param_token, .None); // anytype |
| 2081 | continue; |
| 2082 | }, |
| 2083 | .RParen => break, |
| 2084 | .Comma => { |
| 2085 | try renderToken(ais, tree, last_param_token, .Space); // , |
| 2086 | last_param_token += 1; |
| 2087 | }, |
| 2088 | else => unreachable, |
| 2089 | } |
| 2090 | if (token_tags[last_param_token] == .Identifier) { |
| 2091 | try renderToken(ais, tree, last_param_token, .None); // name |
| 2092 | last_param_token += 1; |
| 2093 | try renderToken(ais, tree, last_param_token, .Space); // : |
| 2094 | last_param_token += 1; |
| 2095 | } |
| 2096 | if (token_tags[last_param_token] == .Keyword_anytype) { |
| 2097 | try renderToken(ais, tree, last_param_token, .None); // anytype |
| 2098 | continue; |
| 2099 | } |
| 2100 | const param = fn_proto.ast.params[param_i]; |
| 2101 | param_i += 1; |
| 2102 | try renderExpression(ais, tree, param, .None); |
| 2103 | last_param_token = tree.lastToken(param) + 1; |
| 2104 | } |
| 2105 | } else { |
| 2106 | // One param per line. |
| 2107 | ais.pushIndent(); |
| 2108 | try renderToken(ais, tree, lparen, .Newline); // ( |
| 2109 | |
| 2110 | var param_i: usize = 0; |
| 2111 | var last_param_token = lparen; |
| 2112 | while (true) { |
| 2113 | last_param_token += 1; |
| 2114 | switch (token_tags[last_param_token]) { |
| 2115 | .DocComment => { |
| 2116 | try renderToken(ais, tree, last_param_token, .Newline); |
| 2117 | continue; |
| 2118 | }, |
| 2119 | .Ellipsis3 => { |
| 2120 | try renderToken(ais, tree, last_param_token, .Comma); // ... |
| 2121 | break; |
| 2122 | }, |
| 2123 | .Keyword_noalias, .Keyword_comptime => { |
| 2124 | try renderToken(ais, tree, last_param_token, .Space); |
| 2125 | last_param_token += 1; |
| 2126 | }, |
| 2127 | .Identifier => {}, |
| 2128 | .Keyword_anytype => { |
| 2129 | try renderToken(ais, tree, last_param_token, .Comma); // anytype |
| 2130 | continue; |
| 2131 | }, |
| 2132 | .RParen => break, |
| 2133 | else => unreachable, |
| 2134 | } |
| 2135 | if (token_tags[last_param_token] == .Identifier) { |
| 2136 | try renderToken(ais, tree, last_param_token, .None); // name |
| 2137 | last_param_token += 1; |
| 2138 | try renderToken(ais, tree, last_param_token, .Space); // : |
| 2139 | last_param_token += 1; |
| 2140 | } |
| 2141 | if (token_tags[last_param_token] == .Keyword_anytype) { |
| 2142 | try renderToken(ais, tree, last_param_token, .Comma); // anytype |
| 2143 | continue; |
| 2144 | } |
| 2145 | const param = fn_proto.ast.params[param_i]; |
| 2146 | param_i += 1; |
| 2147 | try renderExpression(ais, tree, param, .Comma); |
| 2148 | last_param_token = tree.lastToken(param) + 2; |
| 2149 | } |
| 2150 | ais.popIndent(); |
| 2151 | } |
| 2152 | |
| 2153 | try renderToken(ais, tree, rparen, .Space); // ) |
| 2154 | |
| 2155 | if (fn_proto.ast.align_expr != 0) { |
| 2156 | const align_lparen = tree.firstToken(fn_proto.ast.align_expr) - 1; |
| 2157 | const align_rparen = tree.lastToken(fn_proto.ast.align_expr) + 1; |
| 2158 | |
| 2159 | try renderToken(ais, tree, align_lparen - 1, .None); // align |
| 2160 | try renderToken(ais, tree, align_lparen, .None); // ( |
| 2161 | try renderExpression(ais, tree, fn_proto.ast.align_expr, .None); |
| 2162 | try renderToken(ais, tree, align_rparen, .Space); // ) |
| 2163 | } |
| 2164 | |
| 2165 | if (fn_proto.ast.section_expr != 0) { |
| 2166 | const section_lparen = tree.firstToken(fn_proto.ast.section_expr) - 1; |
| 2167 | const section_rparen = tree.lastToken(fn_proto.ast.section_expr) + 1; |
| 2168 | |
| 2169 | try renderToken(ais, tree, section_lparen - 1, .None); // section |
| 2170 | try renderToken(ais, tree, section_lparen, .None); // ( |
| 2171 | try renderExpression(ais, tree, fn_proto.ast.section_expr, .None); |
| 2172 | try renderToken(ais, tree, section_rparen, .Space); // ) |
| 2173 | } |
| 2174 | |
| 2175 | if (fn_proto.ast.callconv_expr != 0) { |
| 2176 | const callconv_lparen = tree.firstToken(fn_proto.ast.callconv_expr) - 1; |
| 2177 | const callconv_rparen = tree.lastToken(fn_proto.ast.callconv_expr) + 1; |
| 2178 | |
| 2179 | try renderToken(ais, tree, callconv_lparen - 1, .None); // callconv |
| 2180 | try renderToken(ais, tree, callconv_lparen, .None); // ( |
| 2181 | try renderExpression(ais, tree, fn_proto.ast.callconv_expr, .None); |
| 2182 | try renderToken(ais, tree, callconv_rparen, .Space); // ) |
| 2183 | } |
| 2184 | |
| 2185 | if (token_tags[maybe_bang] == .Bang) { |
| 2186 | try renderToken(ais, tree, maybe_bang, .None); // ! |
| 2187 | } |
| 2188 | return renderExpression(ais, tree, fn_proto.ast.return_type, space); |
| 2189 | } |
| 2190 | |
| 2191 | fn renderBlock( |
| 2192 | ais: *Ais, |
| 2193 | tree: ast.Tree, |
| 2194 | lbrace: ast.TokenIndex, |
| 2195 | statements: []const ast.Node.Index, |
| 2196 | space: Space, |
| 2197 | ) Error!void { |
| 2198 | const token_tags = tree.tokens.items(.tag); |
| 2199 | const node_tags = tree.nodes.items(.tag); |
| 2200 | |
| 2201 | if (token_tags[lbrace - 1] == .Colon and |
| 2202 | token_tags[lbrace - 2] == .Identifier) |
| 2203 | { |
| 2204 | try renderToken(ais, tree, lbrace - 2, .None); |
| 2205 | try renderToken(ais, tree, lbrace - 1, .Space); |
| 2206 | } |
| 2207 | const nodes_data = tree.nodes.items(.data); |
| 2208 | |
| 2209 | if (statements.len == 0) { |
| 2210 | ais.pushIndentNextLine(); |
| 2211 | try renderToken(ais, tree, lbrace, .None); |
| 2212 | ais.popIndent(); |
| 2213 | const rbrace = lbrace + 1; |
| 2214 | return renderToken(ais, tree, rbrace, space); |
| 2215 | } else { |
| 2216 | ais.pushIndentNextLine(); |
| 2217 | |
| 2218 | try renderToken(ais, tree, lbrace, .Newline); |
| 2219 | |
| 2220 | for (statements) |stmt, i| { |
| 2221 | switch (node_tags[stmt]) { |
| 2222 | .GlobalVarDecl => try renderVarDecl(ais, tree, tree.globalVarDecl(stmt)), |
| 2223 | .LocalVarDecl => try renderVarDecl(ais, tree, tree.localVarDecl(stmt)), |
| 2224 | .SimpleVarDecl => try renderVarDecl(ais, tree, tree.simpleVarDecl(stmt)), |
| 2225 | .AlignedVarDecl => try renderVarDecl(ais, tree, tree.alignedVarDecl(stmt)), |
| 2226 | else => { |
| 2227 | const semicolon = tree.lastToken(stmt) + 1; |
| 2228 | if (token_tags[semicolon] == .Semicolon) { |
| 2229 | try renderExpression(ais, tree, stmt, .None); |
| 2230 | try renderToken(ais, tree, semicolon, .Newline); |
| 2231 | } else { |
| 2232 | try renderExpression(ais, tree, stmt, .Newline); |
| 2233 | } |
| 2234 | }, |
| 2235 | } |
| 2236 | |
| 2237 | if (i + 1 < statements.len) { |
| 2238 | try renderExtraNewline(ais, tree, statements[i + 1]); |
| 2239 | } |
| 2240 | } |
| 2241 | ais.popIndent(); |
| 2242 | // The rbrace could be +1 or +2 from the last token of the last |
| 2243 | // statement in the block because lastToken() does not count semicolons. |
| 2244 | const maybe_rbrace = tree.lastToken(statements[statements.len - 1]) + 1; |
| 2245 | if (token_tags[maybe_rbrace] == .RBrace) { |
| 2246 | return renderToken(ais, tree, maybe_rbrace, space); |
| 2247 | } else { |
| 2248 | assert(token_tags[maybe_rbrace + 1] == .RBrace); |
| 2249 | return renderToken(ais, tree, maybe_rbrace + 1, space); |
| 2250 | } |
| 2251 | } |
| 2252 | } |
| 2253 | |
| 2203 | 2254 | /// Render an expression, and the comma that follows it, if it is present in the source. |
| 2204 | 2255 | fn renderExpressionComma(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Space) Error!void { |
| 2205 | 2256 | const token_tags = tree.tokens.items(.tag); |