From 8758afdf4e5a917a996e36919071947d59af3833 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 21 May 2021 10:21:23 +0100 Subject: [PATCH] General fixes for `odinfmt` --- core/odin/format/format.odin | 33 ++++++++--------- core/odin/printer/printer.odin | 43 +++++++++++---------- core/odin/printer/visit.odin | 68 ++++++++++------------------------ tools/odinfmt/main.odin | 37 +++++++++--------- 4 files changed, 76 insertions(+), 105 deletions(-) diff --git a/core/odin/format/format.odin b/core/odin/format/format.odin index d86808669..10e198958 100644 --- a/core/odin/format/format.odin +++ b/core/odin/format/format.odin @@ -10,26 +10,25 @@ simplify :: proc(file: ^ast.File) { } -format :: proc(source: [] u8, config: printer.Config, allocator := context.allocator) -> ([] u8, bool) { +format :: proc(source: string, config: printer.Config, parser_flags := parser.Flags{}, allocator := context.allocator) -> (string, bool) { + pkg := ast.Package { + kind = .Normal, + }; - pkg := ast.Package { - kind = .Normal, - }; + file := ast.File { + pkg = &pkg, + src = source, + }; - file := ast.File { - pkg = &pkg, - src = source, - }; + p := parser.default_parser(parser_flags); - p := parser.default_parser(); + ok := parser.parse_file(&p, &file); - ok := parser.parse_file(&p, &file); + if !ok || file.syntax_error_count > 0 { + return {}, false; + } - if !ok || file.syntax_error_count > 0 { - return {}, false; - } + prnt := printer.make_printer(config, allocator); - prnt := printer.make_printer(config, allocator); - - return transmute([]u8) printer.print(&prnt, &file), true; -} \ No newline at end of file + return printer.print(&prnt, &file), true; +} diff --git a/core/odin/printer/printer.odin b/core/odin/printer/printer.odin index 2a0be1c3c..0eba91ca2 100644 --- a/core/odin/printer/printer.odin +++ b/core/odin/printer/printer.odin @@ -8,7 +8,7 @@ import "core:fmt" import "core:unicode/utf8" import "core:mem" -Type_Enum :: enum {Line_Comment, Value_Decl, Switch_Stmt, Struct, Assign, Call, Enum, If, For, Proc_Lit} +Type_Enum :: enum {Line_Comment, Value_Decl, Switch_Stmt, Struct, Assign, Call, Enum, If, For, Proc_Lit}; Line_Type :: bit_set[Type_Enum]; @@ -100,21 +100,21 @@ Newline_Style :: enum { } default_style := Config { - spaces = 4, - newline_limit = 2, - convert_do = false, - semicolons = true, - tabs = true, - brace_style = ._1TBS, + spaces = 4, + newline_limit = 2, + convert_do = false, + semicolons = true, + tabs = true, + brace_style = ._1TBS, split_multiple_stmts = true, - align_assignments = true, - align_style = .Align_On_Type_And_Equals, - indent_cases = false, - align_switch = true, - align_structs = true, - align_enums = true, - newline_style = .CRLF, - align_length_break = 9, + align_assignments = true, + align_style = .Align_On_Type_And_Equals, + indent_cases = false, + align_switch = true, + align_structs = true, + align_enums = true, + newline_style = .CRLF, + align_length_break = 9, }; make_printer :: proc(config: Config, allocator := context.allocator) -> Printer { @@ -126,7 +126,6 @@ make_printer :: proc(config: Config, allocator := context.allocator) -> Printer } print :: proc(p: ^Printer, file: ^ast.File) -> string { - p.comments = file.comments; if len(file.decls) > 0 { @@ -387,7 +386,7 @@ format_keyword_to_brace :: proc(p: ^Printer, line_index: int, format_index: int, break; } else if format_token.kind == .Undef { return; - } + } if line_index == 0 && i <= format_index { continue; @@ -500,7 +499,7 @@ align_var_decls :: proc(p: ^Printer) { line.format_tokens[i].kind == .Enum || line.format_tokens[i].kind == .Struct || line.format_tokens[i].kind == .For || - line.format_tokens[i].kind == .If || + line.format_tokens[i].kind == .If || line.format_tokens[i].kind == .Comment { continue_flag = true; } @@ -583,7 +582,7 @@ align_var_decls :: proc(p: ^Printer) { break; } } - + } //repeating myself, move to sub procedure @@ -790,7 +789,7 @@ align_struct :: proc(p: ^Printer, index: int) -> int { length := 0; for format_token, i in line.format_tokens { - + //give up on nested structs if format_token.kind == .Comment { break; @@ -825,7 +824,7 @@ align_struct :: proc(p: ^Printer, index: int) -> int { if colon_count >= brace_token.parameter_count { break; } - } + } //give up aligning nested, it never looks good if nested { @@ -833,7 +832,7 @@ align_struct :: proc(p: ^Printer, index: int) -> int { for format_token in line.format_tokens { if format_token.kind == .Close_Brace { return end_line_index + line_index - index; - } + } } } } diff --git a/core/odin/printer/visit.odin b/core/odin/printer/visit.odin index c2bd8eaf8..bc1222dd2 100644 --- a/core/odin/printer/visit.odin +++ b/core/odin/printer/visit.odin @@ -31,7 +31,6 @@ sort_attribute :: proc(s: ^[dynamic]^ast.Attribute) -> sort.Interface { @(private) comment_before_position :: proc(p: ^Printer, pos: tokenizer.Pos) -> bool { - if len(p.comments) <= p.latest_comment_index { return false; } @@ -48,7 +47,6 @@ next_comment_group :: proc(p: ^Printer) { @(private) push_comment :: proc(p: ^Printer, comment: tokenizer.Token) -> int { - if len(comment.text) == 0 { return 0; } @@ -76,7 +74,6 @@ push_comment :: proc(p: ^Printer, comment: tokenizer.Token) -> int { return 0; } else { - builder := strings.make_builder(context.temp_allocator); c_len := len(comment.text); @@ -156,12 +153,10 @@ push_comment :: proc(p: ^Printer, comment: tokenizer.Token) -> int { @(private) push_comments :: proc(p: ^Printer, pos: tokenizer.Pos) { - prev_comment: ^tokenizer.Token; prev_comment_lines: int; for comment_before_position(p, pos) { - comment_group := p.comments[p.latest_comment_index]; if prev_comment == nil { @@ -170,7 +165,6 @@ push_comments :: proc(p: ^Printer, pos: tokenizer.Pos) { } for comment, i in comment_group.list { - if prev_comment != nil && p.last_source_position.line != comment.pos.line { newline_position(p, min(p.config.newline_limit, comment.pos.line - prev_comment.pos.line - prev_comment_lines)); } @@ -189,7 +183,6 @@ push_comments :: proc(p: ^Printer, pos: tokenizer.Pos) { @(private) append_format_token :: proc(p: ^Printer, format_token: Format_Token) -> ^Format_Token { - format_token := format_token; if p.last_token != nil && (p.last_token.kind == .Ellipsis || p.last_token.kind == .Range_Half || @@ -231,7 +224,6 @@ push_format_token :: proc(p: ^Printer, format_token: Format_Token) { @(private) push_generic_token :: proc(p: ^Printer, kind: tokenizer.Token_Kind, spaces_before: int, value := "") { - format_token := Format_Token { spaces_before = spaces_before, kind = kind, @@ -247,7 +239,6 @@ push_generic_token :: proc(p: ^Printer, kind: tokenizer.Token_Kind, spaces_befor @(private) push_string_token :: proc(p: ^Printer, text: string, spaces_before: int) { - format_token := Format_Token { spaces_before = spaces_before, kind = .String, @@ -259,7 +250,6 @@ push_string_token :: proc(p: ^Printer, text: string, spaces_before: int) { @(private) push_ident_token :: proc(p: ^Printer, text: string, spaces_before: int) { - format_token := Format_Token { spaces_before = spaces_before, kind = .Ident, @@ -295,7 +285,6 @@ move_line_limit :: proc(p: ^Printer, pos: tokenizer.Pos, limit: int) -> bool { @(private) set_line :: proc(p: ^Printer, line: int) -> ^Line { - unwrapped_line: ^Line; if line >= len(p.lines) { @@ -348,7 +337,6 @@ hint_current_line :: proc(p: ^Printer, hint: Line_Type) { @(private) visit_decl :: proc(p: ^Printer, decl: ^ast.Decl, called_in_stmt := false) { - using ast; if decl == nil { @@ -384,7 +372,6 @@ visit_decl :: proc(p: ^Printer, decl: ^ast.Decl, called_in_stmt := false) { push_ident_token(p, path, 0); } case Foreign_Block_Decl: - if len(v.attributes) > 0 { sort.sort(sort_attribute(&v.attributes)); move_line(p, v.attributes[0].pos); @@ -479,14 +466,13 @@ 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, force_newline := false) { - if len(list) == 0 { return; } - //we have to newline the expressions to respect the source + // we have to newline the expressions to respect the source for expr, i in list { - //Don't move the first expression, it looks bad + // Don't move the first expression, it looks bad if i != 0 && force_newline { newline_position(p, 1); } else if i != 0 { @@ -507,7 +493,6 @@ visit_exprs :: proc(p: ^Printer, list: []^ast.Expr, add_comma := false, trailing @(private) visit_attributes :: proc(p: ^Printer, attributes: [dynamic]^ast.Attribute) { - if len(attributes) == 0 { return; } @@ -526,7 +511,6 @@ visit_attributes :: proc(p: ^Printer, attributes: [dynamic]^ast.Attribute) { @(private) visit_stmt :: proc(p: ^Printer, stmt: ^ast.Stmt, block_type: Block_Type = .Generic, empty_block := false, block_stmt := false) { - using ast; if stmt == nil { @@ -734,7 +718,7 @@ visit_stmt :: proc(p: ^Printer, stmt: ^ast.Stmt, block_type: Block_Type = .Gener push_generic_token(p, .Semicolon, 0); } case For_Stmt: - //this should be simplified + // this should be simplified move_line(p, v.pos); if v.label != nil { @@ -796,7 +780,6 @@ visit_stmt :: proc(p: ^Printer, stmt: ^ast.Stmt, block_type: Block_Type = .Gener visit_expr(p, v.expr); visit_stmt(p, v.body); case Range_Stmt: - move_line(p, v.pos); if v.label != nil { @@ -864,7 +847,6 @@ visit_stmt :: proc(p: ^Printer, stmt: ^ast.Stmt, block_type: Block_Type = .Gener } case Branch_Stmt: - move_line(p, v.pos); push_generic_token(p, v.tok.kind, 0); @@ -885,7 +867,6 @@ visit_stmt :: proc(p: ^Printer, stmt: ^ast.Stmt, block_type: Block_Type = .Gener @(private) visit_expr :: proc(p: ^Printer, expr: ^ast.Expr) { - using ast; if expr == nil { @@ -1090,9 +1071,12 @@ visit_expr :: proc(p: ^Printer, expr: ^ast.Expr) { set_source_position(p, v.end); case Proc_Lit: - - if v.inlining == .Inline { + switch v.inlining { + case .None: + case .Inline: push_ident_token(p, "#force_inline", 0); + case .No_Inline: + push_ident_token(p, "#force_no_inline", 0); } visit_proc_type(p, v.type^, true); @@ -1121,11 +1105,13 @@ visit_expr :: proc(p: ^Printer, expr: ^ast.Expr) { case Call_Expr: visit_expr(p, v.expr); - push_format_token(p, Format_Token { - kind = .Open_Paren, - type = .Call, - text = "(", - }); + push_format_token(p, + Format_Token { + kind = .Open_Paren, + type = .Call, + text = "(", + }, + ); hint_current_line(p, {.Call}); @@ -1152,7 +1138,6 @@ visit_expr :: proc(p: ^Printer, expr: ^ast.Expr) { visit_expr(p, v.index); push_generic_token(p, .Close_Bracket, 0); case Proc_Group: - push_generic_token(p, v.tok.kind, 1); if len(v.args) != 0 && v.pos.line != v.args[len(v.args) - 1].pos.line { @@ -1168,7 +1153,6 @@ visit_expr :: proc(p: ^Printer, expr: ^ast.Expr) { } case Comp_Lit: - if v.type != nil { visit_expr(p, v.type); } @@ -1244,7 +1228,6 @@ visit_expr :: proc(p: ^Printer, expr: ^ast.Expr) { } visit_begin_brace :: proc(p: ^Printer, begin: tokenizer.Pos, type: Block_Type, count := 0) { - set_source_position(p, begin); newline_braced := p.config.brace_style == .Allman; @@ -1262,7 +1245,6 @@ visit_begin_brace :: proc(p: ^Printer, begin: tokenizer.Pos, type: Block_Type, c push_format_token(p, format_token); indent(p); } else { - format_token.spaces_before = 1; push_format_token(p, format_token); indent(p); } @@ -1286,13 +1268,11 @@ visit_block_stmts :: proc(p: ^Printer, stmts: []^ast.Stmt, split := false) { } visit_field_list :: proc(p: ^Printer, list: ^ast.Field_List, add_comma := false, trailing := false, enforce_newline := false) { - if list.list == nil { return; } for field, i in list.list { - if !move_line_limit(p, field.pos, 1) && enforce_newline { newline_position(p, 1); } @@ -1325,7 +1305,6 @@ visit_field_list :: proc(p: ^Printer, list: ^ast.Field_List, add_comma := false, } visit_proc_type :: proc(p: ^Printer, proc_type: ast.Proc_Type, is_proc_lit := false) { - if is_proc_lit { push_format_token(p, Format_Token { kind = .Proc, @@ -1357,11 +1336,8 @@ visit_proc_type :: proc(p: ^Printer, proc_type: ast.Proc_Type, is_proc_lit := fa case .Fast_Call: push_string_token(p, "\"fast\"", 1); explicit_calling = true; - case .None: - //nothing i guess - case .Invalid: - //nothing i guess - case .Foreign_Block_Default: + case .None, .Invalid, .Foreign_Block_Default: + // nothing } if explicit_calling { @@ -1405,7 +1381,6 @@ visit_proc_type :: proc(p: ^Printer, proc_type: ast.Proc_Type, is_proc_lit := fa } visit_binary_expr :: proc(p: ^Printer, binary: ast.Binary_Expr) { - move_line(p, binary.left.pos); if v, ok := binary.left.derived.(ast.Binary_Expr); ok { @@ -1430,15 +1405,13 @@ visit_binary_expr :: proc(p: ^Printer, binary: ast.Binary_Expr) { } visit_call_exprs :: proc(p: ^Printer, list: []^ast.Expr, ellipsis := false) { - if len(list) == 0 { return; } - //all the expression are on the line + // all the expression are on the line if list[0].pos.line == list[len(list) - 1].pos.line { for expr, i in list { - if i == len(list) - 1 && ellipsis { push_generic_token(p, .Ellipsis, 0); } @@ -1451,8 +1424,7 @@ visit_call_exprs :: proc(p: ^Printer, list: []^ast.Expr, ellipsis := false) { } } else { for expr, i in list { - - //we have to newline the expressions to respect the source + // we have to newline the expressions to respect the source move_line_limit(p, expr.pos, 1); if i == len(list) - 1 && ellipsis { @@ -1469,13 +1441,11 @@ visit_call_exprs :: proc(p: ^Printer, list: []^ast.Expr, ellipsis := false) { } visit_signature_list :: proc(p: ^Printer, list: ^ast.Field_List, remove_blank := true) { - if list.list == nil { return; } for field, i in list.list { - if i != 0 { move_line_limit(p, field.pos, 1); } diff --git a/tools/odinfmt/main.odin b/tools/odinfmt/main.odin index a651aaff0..63e02269f 100644 --- a/tools/odinfmt/main.odin +++ b/tools/odinfmt/main.odin @@ -14,26 +14,31 @@ Args :: struct { write: Maybe(bool) `flag:"w" usage:"write the new format to file"`, } -print_help :: proc() { +print_help :: proc(args: []string) { + if len(args) == 0 { + fmt.eprint("odinfmt "); + } else { + fmt.eprintf("%s ", args[0]); + } + fmt.eprintln(); } print_arg_error :: proc(error: flag.Flag_Error) { fmt.println(error); } - -format_file :: proc(filepath: string) -> ([]u8, bool) { + +format_file :: proc(filepath: string) -> (string, bool) { if data, ok := os.read_entire_file(filepath); ok { - return format.format(data, format.default_style); + return format.format(string(data), format.default_style); } else { - return {}, false; + return "", false; } } files: [dynamic]string; walk_files :: proc(info: os.File_Info, in_err: os.Errno) -> (err: os.Errno, skip_dir: bool) { - if info.is_dir { return 0, false; } @@ -48,13 +53,12 @@ walk_files :: proc(info: os.File_Info, in_err: os.Errno) -> (err: os.Errno, skip } main :: proc() { - init_global_temporary_allocator(mem.megabytes(100)); args: Args; if len(os.args) < 2 { - print_help(); + print_help(os.args); os.exit(1); } @@ -69,13 +73,13 @@ main :: proc() { if os.is_file(path) { if _, ok := args.write.(bool); ok { - backup_path := strings.concatenate({path, "_bk"}, context.temp_allocator); + backup_path := strings.concatenate({path, "_bk"}); + defer delete(backup_path); if data, ok := format_file(path); ok { - os.rename(path, backup_path); - if os.write_entire_file(path, data) { + if os.write_entire_file(path, transmute([]byte)data) { os.remove(backup_path); } } else { @@ -83,7 +87,7 @@ main :: proc() { } } else { if data, ok := format_file(path); ok { - fmt.println(transmute(string)data); + fmt.println(data); } } } else if os.is_dir(path) { @@ -92,24 +96,23 @@ main :: proc() { for file in files { fmt.println(file); - backup_path := strings.concatenate({file, "_bk"}, context.temp_allocator); + backup_path := strings.concatenate({file, "_bk"}); + defer delete(backup_path); if data, ok := format_file(file); ok { if _, ok := args.write.(bool); ok { os.rename(file, backup_path); - if os.write_entire_file(file, data) { + if os.write_entire_file(file, transmute([]byte)data) { os.remove(backup_path); } } else { - fmt.println(transmute(string)data); + fmt.println(data); } } else { fmt.eprintf("failed to format %v", file); } - - free_all(context.temp_allocator); } fmt.printf("formatted %v files in %vms", len(files), time.duration_milliseconds(time.tick_lap_time(&tick_time)));