From f17fc05ff2431962572bd0fc2ebdc1207251c261 Mon Sep 17 00:00:00 2001 From: Daniel Gavin Date: Fri, 16 Apr 2021 00:44:16 +0200 Subject: [PATCH] format call and binary expression --- core/odin/printer/printer.odin | 208 ++++++++++++++++++++++++++++----- core/odin/printer/visit.odin | 53 ++++++--- 2 files changed, 214 insertions(+), 47 deletions(-) diff --git a/core/odin/printer/printer.odin b/core/odin/printer/printer.odin index 3db48662c..98a7e9ade 100644 --- a/core/odin/printer/printer.odin +++ b/core/odin/printer/printer.odin @@ -8,12 +8,12 @@ import "core:fmt" import "core:unicode/utf8" import "core:mem" -Line_Type_Enum :: enum {Line_Comment, Value_Decl, Switch_Stmt, Struct} +Type_Enum :: enum {Line_Comment, Value_Decl, Switch_Stmt, Struct, Assign, Call, Enum} -Line_Type :: bit_set[Line_Type_Enum]; +Line_Type :: bit_set[Type_Enum]; Line :: struct { - format_tokens: [dynamic] Format_Token, + format_tokens: [dynamic]Format_Token, finalized: bool, used: bool, depth: int, @@ -23,6 +23,7 @@ Line :: struct { Format_Token :: struct { kind: tokenizer.Token_Kind, text: string, + type: Type_Enum, spaces_before: int, parameter_count: int, } @@ -31,13 +32,13 @@ Printer :: struct { string_builder: strings.Builder, config: Config, depth: int, //the identation depth - comments: [dynamic] ^ast.Comment_Group, + comments: [dynamic]^ast.Comment_Group, latest_comment_index: int, allocator: mem.Allocator, file: ^ast.File, source_position: tokenizer.Pos, last_source_position: tokenizer.Pos, - lines: [dynamic] Line, //need to look into a better data structure, one that can handle inserting lines rather than appending + lines: [dynamic]Line, //need to look into a better data structure, one that can handle inserting lines rather than appending skip_semicolon: bool, current_line: ^Line, current_line_index: int, @@ -119,7 +120,7 @@ print :: proc(p: ^Printer, file: ^ast.File) -> string { p.comments = file.comments; if len(file.decls) > 0 { - p.lines = make([dynamic] Line, 0, (file.decls[len(file.decls) - 1].end.line - file.decls[0].pos.line) * 2, context.temp_allocator); + p.lines = make([dynamic]Line, 0, (file.decls[len(file.decls) - 1].end.line - file.decls[0].pos.line) * 2, context.temp_allocator); } set_line(p, 0); @@ -188,15 +189,182 @@ print :: proc(p: ^Printer, file: ^ast.File) -> string { } fix_lines :: proc(p: ^Printer) { - align_var_decls(p); - align_blocks(p); + align_var_decls_and_assignments(p); + format_generic(p); align_comments(p); //align them last since they rely on the other alignments } -align_var_decls :: proc(p: ^Printer) { +format_value_decl :: proc(p: ^Printer, index: int) { + + eq_found := false; + eq_token: Format_Token; + eq_line: int; + largest := 0; + + found_eq: for line, line_index in p.lines[index:] { + for format_token in line.format_tokens { + + largest += len(format_token.text) + format_token.spaces_before; + + if format_token.kind == .Eq { + eq_token = format_token; + eq_line = line_index + index; + eq_found = true; + break found_eq; + } + } + } + + if !eq_found { + return; + } + + align_next := false; + + //check to see if there is a binary operator in the last token(this is guaranteed by the ast visit), otherwise it's not multilined + for line, line_index in p.lines[eq_line:] { + + if len(line.format_tokens) == 0 { + break; + } + + if align_next { + line.format_tokens[0].spaces_before += largest + 1; + align_next = false; + } + + kind := find_last_token(line.format_tokens).kind; + + if tokenizer.Token_Kind.B_Operator_Begin < kind && kind <= tokenizer.Token_Kind.Cmp_Or { + align_next = true; + } + + if !align_next { + break; + } + + } + } -align_switch_smt :: proc(p: ^Printer, index: int) { +find_last_token :: proc(format_tokens: [dynamic]Format_Token) -> Format_Token { + + for i := len(format_tokens)-1; i >= 0; i -= 1 { + + if format_tokens[i].kind != .Comment { + return format_tokens[i]; + } + + } + + panic("not possible"); +} + +format_assignment :: proc(p: ^Printer, index: int) { + +} + +format_call :: proc(p: ^Printer, index: int) { + + paren_found := false; + paren_token: Format_Token; + paren_line: int; + largest := 0; + + found_paren: for line, line_index in p.lines[index:] { + for format_token in line.format_tokens { + + largest += len(format_token.text) + format_token.spaces_before; + + if format_token.kind == .Open_Paren && format_token.type == .Call { + paren_token = format_token; + paren_line = line_index + index; + paren_found = true; + break found_paren; + } else if format_token.kind == .Open_Paren { + return; + } + } + } + + if !paren_found { + return; + } + + paren_count := 1; + done := false; + + for line, line_index in p.lines[paren_line+1:] { + + if len(line.format_tokens) == 0 { + continue; + } + + for format_token, i in line.format_tokens { + + if format_token.kind == .Open_Paren { + paren_count += 1; + } else if format_token.kind == .Close_Paren { + paren_count -= 1; + } + + if paren_count == 0 { + done = true; + } + + } + + line.format_tokens[0].spaces_before += largest; + + if done { + return; + } + + + } + + + +} + +format_generic :: proc(p: ^Printer) { + + for line, line_index in p.lines { + + if len(line.format_tokens) <= 0 { + continue; + } + + if .Switch_Stmt in line.types && p.config.align_switch { + align_switch_stmt(p, line_index); + } + + if .Struct in line.types && p.config.align_structs { + align_struct(p, line_index); + } + + if .Value_Decl in line.types { + format_value_decl(p, line_index); + } + + if .Assign in line.types { + format_assignment(p, line_index); + } + + if .Call in line.types { + format_call(p, line_index); + } + } +} + +align_var_decls_and_assignments :: proc(p: ^Printer) { + + + + +} + +align_switch_stmt :: proc(p: ^Printer, index: int) { switch_found := false; brace_token: Format_Token; @@ -375,24 +543,6 @@ align_struct :: proc(p: ^Printer, index: int) { } } -align_blocks :: proc(p: ^Printer) { - - for line, line_index in p.lines { - - if len(line.format_tokens) <= 0 { - continue; - } - - if .Switch_Stmt in line.types && p.config.align_switch { - align_switch_smt(p, line_index); - } - - if .Struct in line.types && p.config.align_structs { - align_struct(p, line_index); - } - } -} - align_comments :: proc(p: ^Printer) { Comment_Align_Info :: struct { @@ -402,7 +552,7 @@ align_comments :: proc(p: ^Printer) { depth: int, }; - comment_infos := make([dynamic] Comment_Align_Info, 0, context.temp_allocator); + comment_infos := make([dynamic]Comment_Align_Info, 0, context.temp_allocator); current_info: Comment_Align_Info; diff --git a/core/odin/printer/visit.odin b/core/odin/printer/visit.odin index ae3097f03..d8ec98e17 100644 --- a/core/odin/printer/visit.odin +++ b/core/odin/printer/visit.odin @@ -11,19 +11,19 @@ import "core:sort" //right the attribute order is not linearly parsed(bug?) @(private) -sort_attribute :: proc(s: ^[dynamic] ^ast.Attribute) -> sort.Interface { +sort_attribute :: proc(s: ^[dynamic]^ast.Attribute) -> sort.Interface { return sort.Interface { collection = rawptr(s), len = proc(it: sort.Interface) -> int { - s := (^[dynamic] ^ast.Attribute)(it.collection); + s := (^[dynamic]^ast.Attribute)(it.collection); return len(s^); }, less = proc(it: sort.Interface, i, j: int) -> bool { - s := (^[dynamic] ^ast.Attribute)(it.collection); + s := (^[dynamic]^ast.Attribute)(it.collection); return s[i].pos.offset < s[j].pos.offset; }, swap = proc(it: sort.Interface, i, j: int) { - s := (^[dynamic] ^ast.Attribute)(it.collection); + s := (^[dynamic]^ast.Attribute)(it.collection); s[i], s[j] = s[j], s[i]; }, }; @@ -72,7 +72,7 @@ push_comment :: proc(p: ^Printer, comment: tokenizer.Token) -> int { append(&p.current_line.format_tokens, format_token); p.last_token = &p.current_line.format_tokens[len(p.current_line.format_tokens) - 1]; - hint_current_line(p,{.Line_Comment}); + hint_current_line(p, {.Line_Comment}); return 0; } else { @@ -82,7 +82,7 @@ push_comment :: proc(p: ^Printer, comment: tokenizer.Token) -> int { c_len := len(comment.text); trim_space := true; - multilines: [dynamic] string; + multilines: [dynamic]string; for i := 0; i < len(comment.text); i += 1 { @@ -185,7 +185,7 @@ push_comments :: proc(p: ^Printer, pos: tokenizer.Pos) { } if prev_comment != nil { - newline_position(p, min(p.config.newline_limit, p.source_position.line - prev_comment.pos.line)); + newline_position(p, min(p.config.newline_limit, p.source_position.line - prev_comment.pos.line - prev_comment_lines)); } } @@ -303,7 +303,7 @@ set_line :: proc(p: ^Printer, line: int) -> ^Line { if line >= len(p.lines) { for i := len(p.lines); i <= line; i += 1 { new_line: Line; - new_line.format_tokens = make([dynamic] Format_Token, 0, 50, p.allocator); + new_line.format_tokens = make([dynamic]Format_Token, 0, 50, p.allocator); append(&p.lines, new_line); } unwrapped_line = &p.lines[line]; @@ -427,18 +427,20 @@ visit_decl :: proc(p: ^Printer, decl: ^ast.Decl, called_in_stmt := false) { visit_exprs(p, v.names, true); if v.type != nil { - if !v.is_mutable && v.type != nil { + if !v.is_mutable { push_generic_token(p, .Colon, 0); } else { + hint_current_line(p, {.Value_Decl}); push_generic_token(p, .Colon, 0); } visit_expr(p, v.type); } else { - if !v.is_mutable && v.type == nil { + if !v.is_mutable { push_generic_token(p, .Colon, 1); push_generic_token(p, .Colon, 0); } else { + hint_current_line(p, {.Value_Decl}); push_generic_token(p, .Colon, 1); } } @@ -472,7 +474,7 @@ visit_decl :: proc(p: ^Printer, decl: ^ast.Decl, called_in_stmt := false) { } @(private) -visit_exprs :: proc(p: ^Printer, list: [] ^ast.Expr, add_comma := false, trailing := false) { +visit_exprs :: proc(p: ^Printer, list: []^ast.Expr, add_comma := false, trailing := false) { if len(list) == 0 { return; @@ -492,7 +494,7 @@ visit_exprs :: proc(p: ^Printer, list: [] ^ast.Expr, add_comma := false, trailin } @(private) -visit_attributes :: proc(p: ^Printer, attributes: [dynamic] ^ast.Attribute) { +visit_attributes :: proc(p: ^Printer, attributes: [dynamic]^ast.Attribute) { if len(attributes) == 0 { return; @@ -637,7 +639,7 @@ visit_stmt :: proc(p: ^Printer, stmt: ^ast.Stmt, block_type: Block_Type = .Gener push_generic_token(p, .Switch, 1); - hint_current_line(p,{.Switch_Stmt}); + hint_current_line(p, {.Switch_Stmt}); if v.init != nil { p.skip_semicolon = true; @@ -694,6 +696,8 @@ visit_stmt :: proc(p: ^Printer, stmt: ^ast.Stmt, block_type: Block_Type = .Gener case Assign_Stmt: move_line(p, v.pos); + hint_current_line(p, {.Assign}); + visit_exprs(p, v.lhs, true); push_generic_token(p, v.op.kind, 1); @@ -730,11 +734,13 @@ visit_stmt :: proc(p: ^Printer, stmt: ^ast.Stmt, block_type: Block_Type = .Gener } if v.cond != nil { + move_line(p, v.cond.pos); visit_expr(p, v.cond); } if v.post != nil { push_generic_token(p, .Semicolon, 0); + move_line(p, v.post.pos); visit_stmt(p, v.post); } else if v.post == nil && v.cond != nil && v.init != nil { push_generic_token(p, .Semicolon, 0); @@ -946,6 +952,7 @@ visit_expr :: proc(p: ^Printer, expr: ^ast.Expr) { push_generic_token(p, .Open_Bracket, 1); push_generic_token(p, .Dynamic, 0); push_generic_token(p, .Close_Bracket, 0); + merge_next_token(p); visit_expr(p, v.elem); case Bit_Set_Type: push_generic_token(p, .Bit_Set, 1); @@ -1012,7 +1019,7 @@ visit_expr :: proc(p: ^Printer, expr: ^ast.Expr) { case Struct_Type: push_generic_token(p, .Struct, 1); - hint_current_line(p,{.Struct}); + hint_current_line(p, {.Struct}); if v.is_packed { push_ident_token(p, "#packed", 1); @@ -1083,7 +1090,15 @@ visit_expr :: proc(p: ^Printer, expr: ^ast.Expr) { push_ident_token(p, v.field.name, 0); case Call_Expr: visit_expr(p, v.expr); - push_generic_token(p, .Open_Paren, 0); + + push_format_token(p, Format_Token { + kind = .Open_Paren, + type = .Call, + text = "(", + }); + + hint_current_line(p, {.Call}); + visit_call_exprs(p, v.args, v.ellipsis.kind == .Ellipsis); push_generic_token(p, .Close_Paren, 0); case Typeid_Type: @@ -1135,7 +1150,7 @@ visit_expr :: proc(p: ^Printer, expr: ^ast.Expr) { visit_exprs(p, v.elems, true, true); visit_end_brace(p, v.end); } else { - push_generic_token(p, .Open_Brace, 0); + push_generic_token(p, .Open_Brace, 1); visit_exprs(p, v.elems, true); push_generic_token(p, .Close_Brace, 0); } @@ -1182,12 +1197,14 @@ visit_expr :: proc(p: ^Printer, expr: ^ast.Expr) { push_generic_token(p, .Open_Bracket, 1); visit_expr(p, v.len); push_generic_token(p, .Close_Bracket, 0); + merge_next_token(p); visit_expr(p, v.elem); case Map_Type: push_generic_token(p, .Map, 1); push_generic_token(p, .Open_Bracket, 0); visit_expr(p, v.key); push_generic_token(p, .Close_Bracket, 0); + merge_next_token(p); visit_expr(p, v.value); case Helper_Type: visit_expr(p, v.type); @@ -1229,7 +1246,7 @@ visit_end_brace :: proc(p: ^Printer, end: tokenizer.Pos) { p.current_line.depth = p.depth; } -visit_block_stmts :: proc(p: ^Printer, stmts: [] ^ast.Stmt, split := false) { +visit_block_stmts :: proc(p: ^Printer, stmts: []^ast.Stmt, split := false) { for stmt, i in stmts { visit_stmt(p, stmt, .Generic, false, true); @@ -1370,7 +1387,7 @@ visit_binary_expr :: proc(p: ^Printer, binary: ast.Binary_Expr) { } } -visit_call_exprs :: proc(p: ^Printer, list: [] ^ast.Expr, ellipsis := false) { +visit_call_exprs :: proc(p: ^Printer, list: []^ast.Expr, ellipsis := false) { if len(list) == 0 { return;