aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/odin/printer/document.odin66
-rw-r--r--src/odin/printer/printer.odin7
-rw-r--r--src/odin/printer/visit.odin30
3 files changed, 80 insertions, 23 deletions
diff --git a/src/odin/printer/document.odin b/src/odin/printer/document.odin
index 1e5ce3a..d77a490 100644
--- a/src/odin/printer/document.odin
+++ b/src/odin/printer/document.odin
@@ -13,6 +13,7 @@ Document :: union {
Document_Cons,
Document_If_Break,
Document_Align,
+ Document_Nest_If_Break,
}
Document_Nil :: struct {
@@ -33,6 +34,13 @@ Document_Nest :: struct {
document: ^Document,
}
+Document_Nest_If_Break :: struct {
+ indentation: int,
+ alignment: int,
+ document: ^Document,
+ group_id: string,
+}
+
Document_Break :: struct {
value: string,
newline: bool,
@@ -45,6 +53,7 @@ Document_If_Break :: struct {
Document_Group :: struct {
document: ^Document,
mode: Document_Group_Mode,
+ options: Document_Group_Options,
}
Document_Cons :: struct {
@@ -62,6 +71,10 @@ Document_Group_Mode :: enum {
Fit,
}
+Document_Group_Options :: struct {
+ id: string,
+}
+
empty :: proc(allocator := context.allocator) -> ^Document {
document := new(Document, allocator)
document^ = Document_Nil {}
@@ -93,6 +106,16 @@ nest :: proc(level: int, nested_document: ^Document, allocator := context.alloca
return document
}
+nest_if_break :: proc(level: int, nested_document: ^Document, group_id := "", allocator := context.allocator) -> ^Document {
+ document := new(Document, allocator)
+ document^ = Document_Nest_If_Break {
+ indentation = level,
+ document = nested_document,
+ group_id = group_id,
+ }
+ return document
+}
+
hang :: proc(align: int, hanged_document: ^Document, allocator := context.allocator) -> ^Document {
document := new(Document, allocator)
document^ = Document_Nest {
@@ -153,10 +176,11 @@ break_with_no_newline :: proc(allocator := context.allocator) -> ^Document {
return break_with(" ", false, allocator)
}
-group :: proc(grouped_document: ^Document, allocator := context.allocator) -> ^Document {
+group :: proc(grouped_document: ^Document, options := Document_Group_Options{}, allocator := context.allocator) -> ^Document {
document := new(Document, allocator)
document^ = Document_Group {
document = grouped_document,
+ options = options,
}
return document
}
@@ -201,7 +225,7 @@ Tuple :: struct {
document: ^Document,
}
-fits :: proc(width: int, list: ^[dynamic]Tuple, consumed: ^int) -> bool {
+fits :: proc(width: int, list: ^[dynamic]Tuple) -> bool {
assert(list != nil)
start_width := width
@@ -216,8 +240,7 @@ fits :: proc(width: int, list: ^[dynamic]Tuple, consumed: ^int) -> bool {
for len(list) != 0 {
data: Tuple = pop(list)
- if width < 0 {
- consumed^ = start_width
+ if width <= 0 {
return false
}
@@ -225,7 +248,6 @@ fits :: proc(width: int, list: ^[dynamic]Tuple, consumed: ^int) -> bool {
case Document_Nil:
case Document_Newline:
if v.amount > 0 {
- consumed^ = start_width - width
return true
}
case Document_Cons:
@@ -239,7 +261,6 @@ fits :: proc(width: int, list: ^[dynamic]Tuple, consumed: ^int) -> bool {
width -= len(v.value)
case Document_Break:
if data.mode == .Break && v.newline {
- consumed^ = start_width - width
return true
} else {
width -= len(v.value)
@@ -248,14 +269,18 @@ fits :: proc(width: int, list: ^[dynamic]Tuple, consumed: ^int) -> bool {
if data.mode == .Break {
width -= len(v.value)
}
+ case Document_Nest_If_Break:
+ if data.mode == .Break {
+ append(list, Tuple {indentation = data.indentation + v.indentation, mode = data.mode, document = v.document, alignment = data.alignment + v.alignment})
+ } else {
+ append(list, Tuple {indentation = data.indentation, mode = data.mode, document = v.document, alignment = data.alignment})
+ }
case Document_Group:
- append(list, Tuple {indentation = data.indentation, mode = .Flat, document = v.document, alignment = data.alignment})
+ append(list, Tuple {indentation = data.indentation, mode = data.mode, document = v.document, alignment = data.alignment})
}
}
- consumed^ = start_width - width
-
- return width <= 0
+ return width > 0
}
format_newline :: proc(indentation: int, alignment: int, consumed: ^int, builder: ^strings.Builder, p: ^Printer) {
@@ -267,7 +292,7 @@ format_newline :: proc(indentation: int, alignment: int, consumed: ^int, builder
strings.write_string(builder, " ")
}
- consumed^ = indentation + alignment
+ consumed^ = indentation * p.indentation_width + alignment
}
format :: proc(width: int, list: ^[dynamic]Tuple, builder: ^strings.Builder, p: ^Printer) {
@@ -292,7 +317,7 @@ format :: proc(width: int, list: ^[dynamic]Tuple, builder: ^strings.Builder, p:
for i := 0; i < data.alignment; i += 1 {
strings.write_string(builder, " ")
}
- consumed = data.indentation + data.alignment
+ consumed = data.indentation * p.indentation_width + data.alignment
}
case Document_Cons:
append(list, Tuple {indentation = data.indentation, mode = data.mode, document = v.rhs, alignment = data.alignment})
@@ -316,21 +341,26 @@ format :: proc(width: int, list: ^[dynamic]Tuple, builder: ^strings.Builder, p:
strings.write_string(builder, v.value)
consumed += len(v.value)
}
+ case Document_Nest_If_Break:
+ mode := v.group_id != "" ? p.group_modes[v.group_id] : data.mode
+ if mode == .Break {
+ append(list, Tuple {indentation = data.indentation + v.indentation, mode = data.mode, document = v.document, alignment = data.alignment + v.alignment})
+ } else {
+ append(list, Tuple {indentation = data.indentation, mode = data.mode, document = v.document, alignment = data.alignment})
+ }
case Document_Group:
l := make([dynamic]Tuple, 0, len(list))
for element in list {
append(&l, element)
}
-
- append(&l, Tuple {indentation = data.indentation, mode = .Flat, document = v.document, alignment = data.alignment})
-
- fits_consumed := 0
+ append(&l, Tuple {indentation = data.indentation, mode = .Flat, document = v.document, alignment = data.alignment})
+
if data.mode == .Fit {
append(list, Tuple {indentation = data.indentation, mode = .Fit, document = v.document, alignment = data.alignment})
}
- else if fits(width-consumed, &l, &fits_consumed) && v.mode != .Break {
+ else if fits(width-consumed, &l) && v.mode != .Break {
append(list, Tuple {indentation = data.indentation, mode = .Flat, document = v.document, alignment = data.alignment})
} else {
if v.mode == .Fit {
@@ -339,6 +369,8 @@ format :: proc(width: int, list: ^[dynamic]Tuple, builder: ^strings.Builder, p:
append(list, Tuple {indentation = data.indentation, mode = .Break, document = v.document, alignment = data.alignment})
}
}
+
+ p.group_modes[v.options.id] = list[len(list)-1].mode
}
}
}
diff --git a/src/odin/printer/printer.odin b/src/odin/printer/printer.odin
index 5e1cb63..6f39c7c 100644
--- a/src/odin/printer/printer.odin
+++ b/src/odin/printer/printer.odin
@@ -22,8 +22,10 @@ Printer :: struct {
indentation: string,
newline: string,
indentation_count: int,
+ indentation_width: int,
disabled_lines: map[int]Disabled_Info,
disabled_until_line: int,
+ group_modes: map[string]Document_Group_Mode,
src: string,
}
@@ -37,6 +39,7 @@ Config :: struct {
spaces: int, //Spaces per indentation
newline_limit: int, //The limit of newlines between statements and declarations.
tabs: bool, //Enable or disable tabs
+ tabs_width: int,
convert_do: bool, //Convert all do statements to brace blocks
brace_style: Brace_Style,
indent_cases: bool,
@@ -77,6 +80,7 @@ when ODIN_OS == .Windows {
newline_limit = 2,
convert_do = false,
tabs = true,
+ tabs_width = 4,
brace_style = ._1TBS,
indent_cases = false,
newline_style = .CRLF,
@@ -88,6 +92,7 @@ when ODIN_OS == .Windows {
newline_limit = 2,
convert_do = false,
tabs = true,
+ tabs_width = 4,
brace_style = ._1TBS,
indent_cases = false,
newline_style = .LF,
@@ -164,9 +169,11 @@ print_file :: proc(p: ^Printer, file: ^ast.File) -> string {
if p.config.tabs {
p.indentation = "\t"
p.indentation_count = 1
+ p.indentation_width = p.config.tabs_width
} else {
p.indentation_count = p.config.spaces
p.indentation = " "
+ p.indentation_width = 1
}
if p.config.newline_style == .CRLF {
diff --git a/src/odin/printer/visit.odin b/src/odin/printer/visit.odin
index 411a6b4..bc5d57c 100644
--- a/src/odin/printer/visit.odin
+++ b/src/odin/printer/visit.odin
@@ -309,7 +309,11 @@ visit_decl :: proc(p: ^Printer, decl: ^ast.Decl, called_in_stmt := false) -> ^Do
if len(v.values) > 0 {
if is_values_nestable_assign(v.values) {
- return cons(document, nest(p.indentation_count, group(cons_with_opl(group(lhs), group(rhs)))))
+ return cons(document, group(nest(p.indentation_count, cons_with_opl(lhs, group(rhs)))))
+ } else if is_values_nestable_if_break_assign(v.values) {
+ assignments := cons(lhs, group(nest(p.indentation_count, break_with_space()), Document_Group_Options { id = "assignments"}))
+ assignments = cons(assignments, nest_if_break(p.indentation_count, group(rhs), "assignments"))
+ return cons(document, group(assignments))
} else {
return cons(document, group(cons_with_nopl(group(lhs), group(rhs))))
}
@@ -327,7 +331,19 @@ visit_decl :: proc(p: ^Printer, decl: ^ast.Decl, called_in_stmt := false) -> ^Do
is_values_nestable_assign :: proc(list: []^ast.Expr) -> bool {
for expr in list {
#partial switch v in expr.derived {
- case ^ast.Ident, ^ast.Binary_Expr, ^ast.Index_Expr, ^ast.Call_Expr, ^ast.Ternary_If_Expr, ^ast.Ternary_When_Expr, ^ast.Or_Else_Expr, ^ast.Or_Return_Expr:
+ case ^ast.Ident, ^ast.Binary_Expr, ^ast.Index_Expr, ^ast.Ternary_If_Expr, ^ast.Ternary_When_Expr, ^ast.Or_Else_Expr, ^ast.Or_Return_Expr:
+ return true
+ }
+ }
+ return false
+}
+
+
+@(private)
+is_values_nestable_if_break_assign :: proc(list: []^ast.Expr) -> bool {
+ for expr in list {
+ #partial switch v in expr.derived {
+ case ^ast.Call_Expr, ^ast.Comp_Lit:
return true
}
}
@@ -343,7 +359,6 @@ visit_exprs :: proc(p: ^Printer, list: []^ast.Expr, options := List_Options{}, c
document := empty()
for expr, i in list {
-
p.source_position = expr.pos
if .Enforce_Newline in options {
@@ -704,15 +719,18 @@ visit_stmt :: proc(p: ^Printer, stmt: ^ast.Stmt, block_type: Block_Type = .Gener
document = cons_with_nopl(document, visit_stmt(p, v.tag))
document = cons_with_nopl(document, visit_stmt(p, v.body, .Switch_Stmt))
case ^Assign_Stmt:
- assign_document := group(cons_with_nopl(visit_exprs(p, v.lhs, {.Add_Comma, .Glue}), text(v.op.text)))
+ assign_document := group(cons(visit_exprs(p, v.lhs, {.Add_Comma, .Glue}), cons(text(" "), text(v.op.text))))
rhs := visit_exprs(p, v.rhs, {.Add_Comma}, .Assignment_Stmt)
if is_values_nestable_assign(v.rhs) {
document = group(nest(p.indentation_count, cons_with_opl(assign_document, group(rhs))))
+ } else if is_values_nestable_if_break_assign(v.rhs) {
+ document = cons(assign_document, group(nest(p.indentation_count, break_with_space()), Document_Group_Options { id = "assignments"}))
+ document = cons(document, nest_if_break(p.indentation_count, group(rhs), "assignments"))
+ document = group(document)
} else {
- document = group(cons_with_nopl(assign_document, group(rhs)))
+ document = group(cons_with_opl(assign_document, group(rhs)))
}
-
case ^Expr_Stmt:
document = cons(document, visit_expr(p, v.expr))
case ^For_Stmt: