General fixes for odinfmt

This commit is contained in:
gingerBill
2021-05-21 10:21:23 +01:00
parent 362f07d7c5
commit 8758afdf4e
4 changed files with 76 additions and 105 deletions
+3 -4
View File
@@ -10,8 +10,7 @@ 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 { pkg := ast.Package {
kind = .Normal, kind = .Normal,
}; };
@@ -21,7 +20,7 @@ format :: proc(source: [] u8, config: printer.Config, allocator := context.alloc
src = source, src = source,
}; };
p := parser.default_parser(); p := parser.default_parser(parser_flags);
ok := parser.parse_file(&p, &file); ok := parser.parse_file(&p, &file);
@@ -31,5 +30,5 @@ format :: proc(source: [] u8, config: printer.Config, allocator := context.alloc
prnt := printer.make_printer(config, allocator); prnt := printer.make_printer(config, allocator);
return transmute([]u8) printer.print(&prnt, &file), true; return printer.print(&prnt, &file), true;
} }
+1 -2
View File
@@ -8,7 +8,7 @@ import "core:fmt"
import "core:unicode/utf8" import "core:unicode/utf8"
import "core:mem" 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]; Line_Type :: bit_set[Type_Enum];
@@ -126,7 +126,6 @@ make_printer :: proc(config: Config, allocator := context.allocator) -> Printer
} }
print :: proc(p: ^Printer, file: ^ast.File) -> string { print :: proc(p: ^Printer, file: ^ast.File) -> string {
p.comments = file.comments; p.comments = file.comments;
if len(file.decls) > 0 { if len(file.decls) > 0 {
+16 -46
View File
@@ -31,7 +31,6 @@ sort_attribute :: proc(s: ^[dynamic]^ast.Attribute) -> sort.Interface {
@(private) @(private)
comment_before_position :: proc(p: ^Printer, pos: tokenizer.Pos) -> bool { comment_before_position :: proc(p: ^Printer, pos: tokenizer.Pos) -> bool {
if len(p.comments) <= p.latest_comment_index { if len(p.comments) <= p.latest_comment_index {
return false; return false;
} }
@@ -48,7 +47,6 @@ next_comment_group :: proc(p: ^Printer) {
@(private) @(private)
push_comment :: proc(p: ^Printer, comment: tokenizer.Token) -> int { push_comment :: proc(p: ^Printer, comment: tokenizer.Token) -> int {
if len(comment.text) == 0 { if len(comment.text) == 0 {
return 0; return 0;
} }
@@ -76,7 +74,6 @@ push_comment :: proc(p: ^Printer, comment: tokenizer.Token) -> int {
return 0; return 0;
} else { } else {
builder := strings.make_builder(context.temp_allocator); builder := strings.make_builder(context.temp_allocator);
c_len := len(comment.text); c_len := len(comment.text);
@@ -156,12 +153,10 @@ push_comment :: proc(p: ^Printer, comment: tokenizer.Token) -> int {
@(private) @(private)
push_comments :: proc(p: ^Printer, pos: tokenizer.Pos) { push_comments :: proc(p: ^Printer, pos: tokenizer.Pos) {
prev_comment: ^tokenizer.Token; prev_comment: ^tokenizer.Token;
prev_comment_lines: int; prev_comment_lines: int;
for comment_before_position(p, pos) { for comment_before_position(p, pos) {
comment_group := p.comments[p.latest_comment_index]; comment_group := p.comments[p.latest_comment_index];
if prev_comment == nil { if prev_comment == nil {
@@ -170,7 +165,6 @@ push_comments :: proc(p: ^Printer, pos: tokenizer.Pos) {
} }
for comment, i in comment_group.list { for comment, i in comment_group.list {
if prev_comment != nil && p.last_source_position.line != comment.pos.line { 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)); 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) @(private)
append_format_token :: proc(p: ^Printer, format_token: Format_Token) -> ^Format_Token { append_format_token :: proc(p: ^Printer, format_token: Format_Token) -> ^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 || 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) @(private)
push_generic_token :: proc(p: ^Printer, kind: tokenizer.Token_Kind, spaces_before: int, value := "") { push_generic_token :: proc(p: ^Printer, kind: tokenizer.Token_Kind, spaces_before: int, value := "") {
format_token := Format_Token { format_token := Format_Token {
spaces_before = spaces_before, spaces_before = spaces_before,
kind = kind, kind = kind,
@@ -247,7 +239,6 @@ push_generic_token :: proc(p: ^Printer, kind: tokenizer.Token_Kind, spaces_befor
@(private) @(private)
push_string_token :: proc(p: ^Printer, text: string, spaces_before: int) { push_string_token :: proc(p: ^Printer, text: string, spaces_before: int) {
format_token := Format_Token { format_token := Format_Token {
spaces_before = spaces_before, spaces_before = spaces_before,
kind = .String, kind = .String,
@@ -259,7 +250,6 @@ push_string_token :: proc(p: ^Printer, text: string, spaces_before: int) {
@(private) @(private)
push_ident_token :: proc(p: ^Printer, text: string, spaces_before: int) { push_ident_token :: proc(p: ^Printer, text: string, spaces_before: int) {
format_token := Format_Token { format_token := Format_Token {
spaces_before = spaces_before, spaces_before = spaces_before,
kind = .Ident, kind = .Ident,
@@ -295,7 +285,6 @@ move_line_limit :: proc(p: ^Printer, pos: tokenizer.Pos, limit: int) -> bool {
@(private) @(private)
set_line :: proc(p: ^Printer, line: int) -> ^Line { set_line :: proc(p: ^Printer, line: int) -> ^Line {
unwrapped_line: ^Line; unwrapped_line: ^Line;
if line >= len(p.lines) { if line >= len(p.lines) {
@@ -348,7 +337,6 @@ hint_current_line :: proc(p: ^Printer, hint: Line_Type) {
@(private) @(private)
visit_decl :: proc(p: ^Printer, decl: ^ast.Decl, called_in_stmt := false) { visit_decl :: proc(p: ^Printer, decl: ^ast.Decl, called_in_stmt := false) {
using ast; using ast;
if decl == nil { 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); push_ident_token(p, path, 0);
} }
case Foreign_Block_Decl: case Foreign_Block_Decl:
if len(v.attributes) > 0 { if len(v.attributes) > 0 {
sort.sort(sort_attribute(&v.attributes)); sort.sort(sort_attribute(&v.attributes));
move_line(p, v.attributes[0].pos); move_line(p, v.attributes[0].pos);
@@ -479,14 +466,13 @@ visit_decl :: proc(p: ^Printer, decl: ^ast.Decl, called_in_stmt := false) {
@(private) @(private)
visit_exprs :: proc(p: ^Printer, list: []^ast.Expr, add_comma := false, trailing := false, force_newline := false) { visit_exprs :: proc(p: ^Printer, list: []^ast.Expr, add_comma := false, trailing := false, force_newline := false) {
if len(list) == 0 { if len(list) == 0 {
return; 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 { 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 { if i != 0 && force_newline {
newline_position(p, 1); newline_position(p, 1);
} else if i != 0 { } else if i != 0 {
@@ -507,7 +493,6 @@ visit_exprs :: proc(p: ^Printer, list: []^ast.Expr, add_comma := false, trailing
@(private) @(private)
visit_attributes :: proc(p: ^Printer, attributes: [dynamic]^ast.Attribute) { visit_attributes :: proc(p: ^Printer, attributes: [dynamic]^ast.Attribute) {
if len(attributes) == 0 { if len(attributes) == 0 {
return; return;
} }
@@ -526,7 +511,6 @@ visit_attributes :: proc(p: ^Printer, attributes: [dynamic]^ast.Attribute) {
@(private) @(private)
visit_stmt :: proc(p: ^Printer, stmt: ^ast.Stmt, block_type: Block_Type = .Generic, empty_block := false, block_stmt := false) { visit_stmt :: proc(p: ^Printer, stmt: ^ast.Stmt, block_type: Block_Type = .Generic, empty_block := false, block_stmt := false) {
using ast; using ast;
if stmt == nil { 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); push_generic_token(p, .Semicolon, 0);
} }
case For_Stmt: case For_Stmt:
//this should be simplified // this should be simplified
move_line(p, v.pos); move_line(p, v.pos);
if v.label != nil { 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_expr(p, v.expr);
visit_stmt(p, v.body); visit_stmt(p, v.body);
case Range_Stmt: case Range_Stmt:
move_line(p, v.pos); move_line(p, v.pos);
if v.label != nil { if v.label != nil {
@@ -864,7 +847,6 @@ visit_stmt :: proc(p: ^Printer, stmt: ^ast.Stmt, block_type: Block_Type = .Gener
} }
case Branch_Stmt: case Branch_Stmt:
move_line(p, v.pos); move_line(p, v.pos);
push_generic_token(p, v.tok.kind, 0); 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) @(private)
visit_expr :: proc(p: ^Printer, expr: ^ast.Expr) { visit_expr :: proc(p: ^Printer, expr: ^ast.Expr) {
using ast; using ast;
if expr == nil { if expr == nil {
@@ -1090,9 +1071,12 @@ visit_expr :: proc(p: ^Printer, expr: ^ast.Expr) {
set_source_position(p, v.end); set_source_position(p, v.end);
case Proc_Lit: case Proc_Lit:
switch v.inlining {
if v.inlining == .Inline { case .None:
case .Inline:
push_ident_token(p, "#force_inline", 0); 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); visit_proc_type(p, v.type^, true);
@@ -1121,11 +1105,13 @@ visit_expr :: proc(p: ^Printer, expr: ^ast.Expr) {
case Call_Expr: case Call_Expr:
visit_expr(p, v.expr); visit_expr(p, v.expr);
push_format_token(p, Format_Token { push_format_token(p,
Format_Token {
kind = .Open_Paren, kind = .Open_Paren,
type = .Call, type = .Call,
text = "(", text = "(",
}); },
);
hint_current_line(p, {.Call}); hint_current_line(p, {.Call});
@@ -1152,7 +1138,6 @@ visit_expr :: proc(p: ^Printer, expr: ^ast.Expr) {
visit_expr(p, v.index); visit_expr(p, v.index);
push_generic_token(p, .Close_Bracket, 0); push_generic_token(p, .Close_Bracket, 0);
case Proc_Group: case Proc_Group:
push_generic_token(p, v.tok.kind, 1); push_generic_token(p, v.tok.kind, 1);
if len(v.args) != 0 && v.pos.line != v.args[len(v.args) - 1].pos.line { 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: case Comp_Lit:
if v.type != nil { if v.type != nil {
visit_expr(p, v.type); 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) { visit_begin_brace :: proc(p: ^Printer, begin: tokenizer.Pos, type: Block_Type, count := 0) {
set_source_position(p, begin); set_source_position(p, begin);
newline_braced := p.config.brace_style == .Allman; 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); push_format_token(p, format_token);
indent(p); indent(p);
} else { } else {
format_token.spaces_before = 1;
push_format_token(p, format_token); push_format_token(p, format_token);
indent(p); 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) { visit_field_list :: proc(p: ^Printer, list: ^ast.Field_List, add_comma := false, trailing := false, enforce_newline := false) {
if list.list == nil { if list.list == nil {
return; return;
} }
for field, i in list.list { for field, i in list.list {
if !move_line_limit(p, field.pos, 1) && enforce_newline { if !move_line_limit(p, field.pos, 1) && enforce_newline {
newline_position(p, 1); 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) { visit_proc_type :: proc(p: ^Printer, proc_type: ast.Proc_Type, is_proc_lit := false) {
if is_proc_lit { if is_proc_lit {
push_format_token(p, Format_Token { push_format_token(p, Format_Token {
kind = .Proc, kind = .Proc,
@@ -1357,11 +1336,8 @@ visit_proc_type :: proc(p: ^Printer, proc_type: ast.Proc_Type, is_proc_lit := fa
case .Fast_Call: case .Fast_Call:
push_string_token(p, "\"fast\"", 1); push_string_token(p, "\"fast\"", 1);
explicit_calling = true; explicit_calling = true;
case .None: case .None, .Invalid, .Foreign_Block_Default:
//nothing i guess // nothing
case .Invalid:
//nothing i guess
case .Foreign_Block_Default:
} }
if explicit_calling { 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) { visit_binary_expr :: proc(p: ^Printer, binary: ast.Binary_Expr) {
move_line(p, binary.left.pos); move_line(p, binary.left.pos);
if v, ok := binary.left.derived.(ast.Binary_Expr); ok { 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) { visit_call_exprs :: proc(p: ^Printer, list: []^ast.Expr, ellipsis := false) {
if len(list) == 0 { if len(list) == 0 {
return; 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 { if list[0].pos.line == list[len(list) - 1].pos.line {
for expr, i in list { for expr, i in list {
if i == len(list) - 1 && ellipsis { if i == len(list) - 1 && ellipsis {
push_generic_token(p, .Ellipsis, 0); push_generic_token(p, .Ellipsis, 0);
} }
@@ -1451,8 +1424,7 @@ visit_call_exprs :: proc(p: ^Printer, list: []^ast.Expr, ellipsis := false) {
} }
} else { } else {
for expr, i in list { 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); move_line_limit(p, expr.pos, 1);
if i == len(list) - 1 && ellipsis { 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) { visit_signature_list :: proc(p: ^Printer, list: ^ast.Field_List, remove_blank := true) {
if list.list == nil { if list.list == nil {
return; return;
} }
for field, i in list.list { for field, i in list.list {
if i != 0 { if i != 0 {
move_line_limit(p, field.pos, 1); move_line_limit(p, field.pos, 1);
} }
+19 -16
View File
@@ -14,26 +14,31 @@ Args :: struct {
write: Maybe(bool) `flag:"w" usage:"write the new format to file"`, 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) { print_arg_error :: proc(error: flag.Flag_Error) {
fmt.println(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 { 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 { } else {
return {}, false; return "", false;
} }
} }
files: [dynamic]string; files: [dynamic]string;
walk_files :: proc(info: os.File_Info, in_err: os.Errno) -> (err: os.Errno, skip_dir: bool) { walk_files :: proc(info: os.File_Info, in_err: os.Errno) -> (err: os.Errno, skip_dir: bool) {
if info.is_dir { if info.is_dir {
return 0, false; return 0, false;
} }
@@ -48,13 +53,12 @@ walk_files :: proc(info: os.File_Info, in_err: os.Errno) -> (err: os.Errno, skip
} }
main :: proc() { main :: proc() {
init_global_temporary_allocator(mem.megabytes(100)); init_global_temporary_allocator(mem.megabytes(100));
args: Args; args: Args;
if len(os.args) < 2 { if len(os.args) < 2 {
print_help(); print_help(os.args);
os.exit(1); os.exit(1);
} }
@@ -69,13 +73,13 @@ main :: proc() {
if os.is_file(path) { if os.is_file(path) {
if _, ok := args.write.(bool); ok { 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 { if data, ok := format_file(path); ok {
os.rename(path, backup_path); 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); os.remove(backup_path);
} }
} else { } else {
@@ -83,7 +87,7 @@ main :: proc() {
} }
} else { } else {
if data, ok := format_file(path); ok { if data, ok := format_file(path); ok {
fmt.println(transmute(string)data); fmt.println(data);
} }
} }
} else if os.is_dir(path) { } else if os.is_dir(path) {
@@ -92,24 +96,23 @@ main :: proc() {
for file in files { for file in files {
fmt.println(file); 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 data, ok := format_file(file); ok {
if _, ok := args.write.(bool); ok { if _, ok := args.write.(bool); ok {
os.rename(file, backup_path); 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); os.remove(backup_path);
} }
} else { } else {
fmt.println(transmute(string)data); fmt.println(data);
} }
} else { } else {
fmt.eprintf("failed to format %v", file); 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))); fmt.printf("formatted %v files in %vms", len(files), time.duration_milliseconds(time.tick_lap_time(&tick_time)));