瀏覽代碼

format call and binary expression

Daniel Gavin 4 年之前
父節點
當前提交
f17fc05ff2
共有 2 個文件被更改,包括 214 次插入47 次删除
  1. 179 29
      core/odin/printer/printer.odin
  2. 35 18
      core/odin/printer/visit.odin

+ 179 - 29
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;
+		}
+
+	}
+
+}
+
+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) {
+	
 }
 
-align_switch_smt :: 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;
 

+ 35 - 18
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;