aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDaniel Gavin <danielgavin5@hotmail.com>2022-07-09 18:36:01 +0200
committerDaniel Gavin <danielgavin5@hotmail.com>2022-07-09 18:36:01 +0200
commit28d4e76ecc635c1c386ff914d4db6c92eea092e8 (patch)
treee7b181f43a0e65358917988c11ad2e04c0cbeabd /src
parent9e9f4958f0ff2686cd0ace5a247c54c5ab775106 (diff)
parentfb5b19056827afbad2133f486d68d2ea162930e7 (diff)
Merge branch 'master' into index-caching
Diffstat (limited to 'src')
-rw-r--r--src/common/config.odin1
-rw-r--r--src/common/util_windows.odin10
-rw-r--r--src/odin/printer/document.odin86
-rw-r--r--src/odin/printer/printer.odin7
-rw-r--r--src/odin/printer/visit.odin239
-rw-r--r--src/server/analysis.odin12
-rw-r--r--src/server/format.odin16
7 files changed, 260 insertions, 111 deletions
diff --git a/src/common/config.odin b/src/common/config.odin
index 387e8b8..d90e5fa 100644
--- a/src/common/config.odin
+++ b/src/common/config.odin
@@ -28,6 +28,7 @@ Config :: struct {
Format_Config :: struct {
tabs: bool,
characters: int,
+ spaces: int,
}
config: Config; \ No newline at end of file
diff --git a/src/common/util_windows.odin b/src/common/util_windows.odin
index 194bd4d..716d4be 100644
--- a/src/common/util_windows.odin
+++ b/src/common/util_windows.odin
@@ -32,10 +32,10 @@ get_case_sensitive_path :: proc(path: string, allocator := context.temp_allocato
file := win32.CreateFileW(&wide[0], 0, win32.FILE_SHARE_READ, nil, win32.OPEN_EXISTING, win32.FILE_FLAG_BACKUP_SEMANTICS, nil)
if(file == win32.INVALID_HANDLE)
- {
+ {
log_last_error()
- return "";
- }
+ return "";
+ }
buffer := make([]u16, 512, context.temp_allocator)
@@ -43,6 +43,8 @@ get_case_sensitive_path :: proc(path: string, allocator := context.temp_allocato
res, _ := win32.utf16_to_utf8(buffer[4:], allocator)
+ win32.CloseHandle(file)
+
return res
}
@@ -127,4 +129,4 @@ run_executable :: proc(command: string, stdout: ^[]byte) -> (u32, bool, []byte)
win32.CloseHandle(stdout_read)
return exit_code, true, stdout[0:index]
-} \ No newline at end of file
+}
diff --git a/src/odin/printer/document.odin b/src/odin/printer/document.odin
index 1f104a3..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 {
@@ -59,10 +68,13 @@ Document_Align :: struct {
Document_Group_Mode :: enum {
Flat,
Break,
- Fill,
Fit,
}
+Document_Group_Options :: struct {
+ id: string,
+}
+
empty :: proc(allocator := context.allocator) -> ^Document {
document := new(Document, allocator)
document^ = Document_Nil {}
@@ -94,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 {
@@ -154,19 +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 {
- document := new(Document, allocator)
- document^ = Document_Group {
- document = grouped_document,
- }
- return document
-}
-
-fill_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,
- mode = .Fill,
+ options = options,
}
return document
}
@@ -211,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
@@ -226,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
}
@@ -235,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:
@@ -249,9 +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 if data.mode == .Fill && v.newline && width > 0 {
return true
} else {
width -= len(v.value)
@@ -260,13 +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 true
+ return width > 0
}
format_newline :: proc(indentation: int, alignment: int, consumed: ^int, builder: ^strings.Builder, p: ^Printer) {
@@ -278,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) {
@@ -303,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})
@@ -318,11 +332,6 @@ format :: proc(width: int, list: ^[dynamic]Tuple, builder: ^strings.Builder, p:
case Document_Break:
if data.mode == .Break && v.newline {
format_newline(data.indentation, data.alignment, &consumed, builder, p)
- } else if data.mode == .Fill && consumed + len(v.value) < width {
- strings.write_string(builder, v.value)
- consumed += len(v.value)
- } else if data.mode == .Fill && v.newline {
- format_newline(data.indentation, data.alignment, &consumed, builder, p)
} else {
strings.write_string(builder, v.value)
consumed += len(v.value)
@@ -332,31 +341,36 @@ 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 == .Fill {
- append(list, Tuple {indentation = data.indentation, mode = .Fill, document = v.document, alignment = data.alignment})
- } else if v.mode == .Fit {
+ if v.mode == .Fit {
append(list, Tuple {indentation = data.indentation, mode = .Fit, document = v.document, alignment = data.alignment})
} else {
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 4e07f02..14d5d4e 100644
--- a/src/odin/printer/visit.odin
+++ b/src/odin/printer/visit.odin
@@ -1,10 +1,12 @@
package odin_printer
import "core:odin/ast"
+import "core:odin/parser"
import "core:odin/tokenizer"
import "core:strings"
import "core:fmt"
import "core:sort"
+import "core:strconv"
//right now the attribute order is not linearly parsed(bug?)
@(private)
@@ -306,11 +308,15 @@ visit_decl :: proc(p: ^Printer, decl: ^ast.Decl, called_in_stmt := false) -> ^Do
}
if len(v.values) > 0 {
- if is_values_binary(p, v.values) {
- return cons(document, fill_group(cons_with_opl(group(lhs), align(fill_group(rhs)))))
+ if is_values_nestable_assign(v.values) {
+ 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))))
- }
+ return cons(document, group(cons_with_nopl(group(lhs), group(rhs))))
+ }
} else {
return cons(document, group(lhs))
}
@@ -322,10 +328,23 @@ visit_decl :: proc(p: ^Printer, decl: ^ast.Decl, called_in_stmt := false) -> ^Do
}
@(private)
-is_values_binary :: proc(p: ^Printer, list: []^ast.Expr) -> bool {
+is_values_nestable_assign :: proc(list: []^ast.Expr) -> bool {
for expr in list {
- if _, bin := expr.derived.(^ast.Binary_Expr); bin {
- return true
+ #partial switch v in expr.derived {
+ 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
}
}
return false
@@ -340,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 {
@@ -422,7 +440,7 @@ visit_union_exprs :: proc(p: ^Printer, union_type: ast.Union_Type, options := Li
for expr, i in union_type.variants {
if i == 0 && .Enforce_Newline in options {
- comment, ok := visit_comments(p, union_type.variants[i].pos)
+ comment, ok := visit_comments(p, union_type.variants[i].pos)
if _, is_nil := comment.(Document_Nil); !is_nil {
comment = cons(comment, newline(1))
}
@@ -531,6 +549,9 @@ visit_state_flags :: proc(p: ^Printer, flags: ast.Node_State_Flags) -> ^Document
if .No_Bounds_Check in flags {
return cons(text("#no_bounds_check"), break_with_no_newline())
}
+ if .Bounds_Check in flags {
+ return cons(text("#bounds_check"), break_with_no_newline())
+ }
return empty()
}
@@ -621,7 +642,7 @@ visit_stmt :: proc(p: ^Printer, stmt: ^ast.Stmt, block_type: Block_Type = .Gener
}
if v.cond != nil {
- if_document = cons_with_nopl(if_document, fill_group(visit_expr(p, v.cond)))
+ if_document = cons_with_nopl(if_document, group(visit_expr(p, v.cond)))
}
document = cons(document, group(hang(3, if_document)))
@@ -698,18 +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)))
-
- if block_stmt {
- if should_align_assignment_stmt(p, v^) {
- assign_document = fill_group(cons(assign_document, align(cons(break_with_space(), visit_exprs(p, v.rhs, {.Add_Comma}, .Assignment_Stmt)))))
- } else {
- assign_document = fill_group(cons(assign_document, cons(break_with_space(), visit_exprs(p, v.rhs, {.Add_Comma}, .Assignment_Stmt))))
- }
+ 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 {
- assign_document = cons_with_nopl(assign_document, visit_exprs(p, v.rhs, {.Add_Comma}, .Assignment_Stmt))
+ document = group(cons_with_opl(assign_document, group(rhs)))
}
- document = cons(document, group(assign_document))
case ^Expr_Stmt:
document = cons(document, visit_expr(p, v.expr))
case ^For_Stmt:
@@ -730,7 +751,7 @@ visit_stmt :: proc(p: ^Printer, stmt: ^ast.Stmt, block_type: Block_Type = .Gener
if v.cond != nil {
set_source_position(p, v.cond.pos)
- for_document = cons_with_opl(for_document, fill_group(visit_expr(p, v.cond)))
+ for_document = cons_with_opl(for_document, group(visit_expr(p, v.cond)))
}
if v.post != nil {
@@ -895,20 +916,6 @@ contains_do_in_expression :: proc(p: ^Printer, expr: ^ast.Expr) -> bool {
}
@(private)
-should_align_assignment_stmt :: proc(p: ^Printer, stmt: ast.Assign_Stmt) -> bool {
- if len(stmt.rhs) == 0 {
- return false
- }
-
- for expr in stmt.rhs {
- if _, ok := stmt.rhs[0].derived.(^ast.Binary_Expr); ok {
- return true
- }
- }
- return false
-}
-
-@(private)
push_where_clauses :: proc(p: ^Printer, clauses: []^ast.Expr) -> ^Document {
if len(clauses) == 0 {
return empty()
@@ -1054,7 +1061,7 @@ visit_expr :: proc(p: ^Printer, expr: ^ast.Expr, called_from: Expr_Called_Type =
document = cons_with_nopl(document, text("{"))
document = cons(document, text("}"))
} else {
- document = cons_with_opl(document, visit_begin_brace(p, v.pos, .Generic))
+ document = cons_with_nopl(document, visit_begin_brace(p, v.pos, .Generic))
set_source_position(p, v.variants[0].pos)
document = cons(document, nest(p.indentation_count, cons(newline_position(p, 1, v.pos), visit_union_exprs(p, v^, {.Add_Comma, .Trailing, .Enforce_Newline}))))
set_source_position(p, v.end)
@@ -1139,7 +1146,7 @@ visit_expr :: proc(p: ^Printer, expr: ^ast.Expr, called_from: Expr_Called_Type =
case ^Basic_Lit:
document = text_token(p, v.tok)
case ^Binary_Expr:
- document = visit_binary_expr(p, v^)
+ document = visit_binary_expr(p, v^, true)
case ^Implicit_Selector_Expr:
document = cons(text("."), text_position(p, v.field.name, v.field.pos))
case ^Call_Expr:
@@ -1173,17 +1180,17 @@ visit_expr :: proc(p: ^Printer, expr: ^ast.Expr, called_from: Expr_Called_Type =
case ^Selector_Expr:
document = cons(visit_expr(p, v.expr), cons(text_token(p, v.op), visit_expr(p, v.field)))
case ^Paren_Expr:
- document = cons(text("("), cons(visit_expr(p, v.expr), text(")")))
+ document = group(cons(text("("), cons(nest(p.indentation_count, visit_expr(p, v.expr)), text(")"))))
case ^Index_Expr:
document = visit_expr(p, v.expr)
document = cons(document, text("["))
- document = cons(document, fill_group(align(visit_expr(p, v.index))))
+ document = cons(document, group(align(visit_expr(p, v.index))))
document = cons(document, text("]"))
case ^Proc_Group:
document = text_token(p, v.tok)
if len(v.args) != 0 {
- document = cons_with_opl(document, visit_begin_brace(p, v.pos, .Generic))
+ document = cons_with_nopl(document, visit_begin_brace(p, v.pos, .Generic))
set_source_position(p, v.args[0].pos)
document = cons(document, nest(p.indentation_count, cons(newline_position(p, 1, v.args[0].pos), visit_exprs(p, v.args, {.Add_Comma, .Trailing, .Enforce_Newline}))))
document = cons(document, visit_end_brace(p, v.end, 1))
@@ -1199,17 +1206,28 @@ visit_expr :: proc(p: ^Printer, expr: ^ast.Expr, called_from: Expr_Called_Type =
if v.type != nil {
document = cons_with_nopl(document, visit_expr(p, v.type))
- }
+
+ if matrix_type, ok := v.type.derived.(^ast.Matrix_Type); ok && len(v.elems) > 0 && is_matrix_type_constant(matrix_type) {
+ document = cons_with_nopl(document, visit_begin_brace(p, v.pos, .Generic))
+
+ set_source_position(p, v.open)
+ document = cons(document, nest(p.indentation_count, cons(newline_position(p, 1, v.elems[0].pos), visit_matrix_comp_lit(p, v, matrix_type))))
+ set_source_position(p, v.end)
- //If we call from the value declartion, we want it to be nicely newlined and aligned
+ document = cons(document, cons(newline(1), text_position(p, "}", v.end)))
+
+ break
+ }
+ }
+
if (should_align_comp_lit(p, v^) || contains_comments_in_range(p, v.pos, v.end)) && (called_from == .Value_Decl || called_from == .Assignment_Stmt) && len(v.elems) != 0 {
- document = cons_with_opl(document, visit_begin_brace(p, v.pos, .Generic))
+ document = cons_with_nopl(document, visit_begin_brace(p, v.pos, .Generic))
set_source_position(p, v.open)
document = cons(document, nest(p.indentation_count, cons(newline_position(p, 1, v.elems[0].pos), visit_comp_lit_exprs(p, v^, {.Add_Comma, .Trailing, .Enforce_Newline}))))
set_source_position(p, v.end)
- document = cons(document, cons(newline(1), text_position(p, "}", v.end)))
+ document = cons(document, cons(newline(1), text_position(p, "}", v.end)))
} else {
document = cons(document, text("{"))
document = cons(document, nest(p.indentation_count, cons(break_with(""), visit_exprs(p, v.elems, {.Add_Comma, .Group}))))
@@ -1232,11 +1250,11 @@ visit_expr :: proc(p: ^Printer, expr: ^ast.Expr, called_from: Expr_Called_Type =
document = cons(document, text(")"))
}
case ^Pointer_Type:
- return cons(text("^"), visit_expr(p, v.elem))
+ document = cons(text("^"), visit_expr(p, v.elem))
case ^Multi_Pointer_Type:
- return cons(text("[^]"), visit_expr(p, v.elem))
+ document = cons(text("[^]"), visit_expr(p, v.elem))
case ^Implicit:
- return text_token(p, v.tok)
+ document = text_token(p, v.tok)
case ^Poly_Type:
document = cons(text("$"), visit_expr(p, v.type))
@@ -1256,7 +1274,10 @@ visit_expr :: proc(p: ^Printer, expr: ^ast.Expr, called_from: Expr_Called_Type =
document = cons(document, text("]"))
document = cons(document, visit_expr(p, v.value))
case ^Helper_Type:
- document = visit_expr(p, v.type)
+ if v.tok == .Hash {
+ document = cons(document, text("#type"))
+ }
+ document = cons_with_nopl(document, visit_expr(p, v.type))
case ^Matrix_Type:
document = text_position(p, "matrix", v.pos)
document = cons(document, text("["))
@@ -1264,7 +1285,7 @@ visit_expr :: proc(p: ^Printer, expr: ^ast.Expr, called_from: Expr_Called_Type =
document = cons(document, text(","))
document = cons_with_opl(document, visit_expr(p, v.column_count))
document = cons(document, text("]"))
- document = cons(document, visit_expr(p, v.elem))
+ document = cons(group(document), visit_expr(p, v.elem))
case ^Matrix_Index_Expr:
document = visit_expr(p, v.expr)
document = cons(document, text("["))
@@ -1280,6 +1301,44 @@ visit_expr :: proc(p: ^Printer, expr: ^ast.Expr, called_from: Expr_Called_Type =
}
@(private)
+is_matrix_type_constant :: proc(matrix_type: ^ast.Matrix_Type) -> bool {
+ if row_count, is_lit := matrix_type.row_count.derived.(^ast.Basic_Lit); is_lit {
+ _, ok := strconv.parse_int(row_count.tok.text)
+ return ok
+ }
+
+ if column_count, is_lit := matrix_type.column_count.derived.(^ast.Basic_Lit); is_lit {
+ _, ok := strconv.parse_int(column_count.tok.text)
+ return ok
+ }
+
+ return false
+}
+
+@(private)
+visit_matrix_comp_lit :: proc(p: ^Printer, comp_lit: ^ast.Comp_Lit, matrix_type: ^ast.Matrix_Type) -> ^Document {
+ document := empty()
+
+ //these values have already been validated
+ row_count, _ := strconv.parse_int(matrix_type.row_count.derived.(^ast.Basic_Lit).tok.text)
+ column_count, _ := strconv.parse_int(matrix_type.column_count.derived.(^ast.Basic_Lit).tok.text)
+
+ for row := 0; row < row_count; row += 1 {
+ for column := 0; column < column_count; column += 1 {
+ document = cons(document, visit_expr(p, comp_lit.elems[column + row * column_count]))
+ document = cons(document, text(", "))
+ }
+
+ if row_count - 1 != row {
+ document = cons(document, newline(1))
+ }
+ }
+
+ return document
+}
+
+
+@(private)
visit_begin_brace :: proc(p: ^Printer, begin: tokenizer.Pos, type: Block_Type, count := 0, same_line_spaces_before := 1) -> ^Document {
set_source_position(p, begin)
@@ -1409,6 +1468,29 @@ visit_field_list :: proc(p: ^Printer, list: ^ast.Field_List, options := List_Opt
}
@(private)
+visit_proc_tags :: proc(p: ^Printer, proc_tags: ast.Proc_Tags) -> ^Document {
+ document := empty()
+
+ if .Bounds_Check in proc_tags {
+ document = cons_with_opl(document, text("#bounds_check"))
+ }
+
+ if .No_Bounds_Check in proc_tags {
+ document = cons_with_opl(document, text("#no_bounds_check"))
+ }
+
+ if .Optional_Ok in proc_tags {
+ document = cons_with_opl(document, text("#optional_ok"))
+ }
+
+ if .Optional_Second in proc_tags {
+ document = cons_with_opl(document, text("#optional_second"))
+ }
+
+ return document
+}
+
+@(private)
visit_proc_type :: proc(p: ^Printer, proc_type: ast.Proc_Type) -> ^Document {
document := text("proc")
@@ -1459,29 +1541,49 @@ visit_proc_type :: proc(p: ^Printer, proc_type: ast.Proc_Type) -> ^Document {
document = cons_with_nopl(document, text("!"))
}
+ document = cons_with_opl(document, visit_proc_tags(p, proc_type.tags))
+
return document
}
+
@(private)
-visit_binary_expr :: proc(p: ^Printer, binary: ast.Binary_Expr) -> ^Document {
- lhs: ^Document
- rhs: ^Document
+visit_binary_expr :: proc(p: ^Printer, binary: ast.Binary_Expr, first := false) -> ^Document {
+ document := empty()
- if v, ok := binary.left.derived.(^ast.Binary_Expr); ok {
- lhs = visit_binary_expr(p, v^)
- } else {
- lhs = visit_expr(p, binary.left)
- }
+ nest_first_expression := false
- if v, ok := binary.right.derived.(^ast.Binary_Expr); ok {
- rhs = visit_binary_expr(p, v^)
- } else {
- rhs = visit_expr(p, binary.right)
+ if binary.left != nil {
+ if b, ok := binary.left.derived.(^ast.Binary_Expr); ok {
+ pa := parser.Parser {
+ allow_in_expr = true,
+ }
+ nest_first_expression = parser.token_precedence(&pa, b.op.kind) != parser.token_precedence(&pa, binary.op.kind)
+ document = cons(document, visit_binary_expr(p, b^))
+ } else {
+ document = cons(document, visit_expr(p, binary.left))
+ }
+ }
+
+ if true {
+ if nest_first_expression {
+ document = nest(p.indentation_count, document)
+ document = group(document)
+ }
+
}
- op := text(binary.op.text)
+ document = cons_with_nopl(document, text(binary.op.text))
- return cons_with_nopl(lhs, cons_with_opl(op, rhs))
+ if binary.right != nil {
+ if b, ok := binary.right.derived.(^ast.Binary_Expr); ok {
+ document = cons_with_opl(document, group(nest(p.indentation_count, visit_binary_expr(p, b^))))
+ } else {
+ document = cons_with_opl(document, group(nest(p.indentation_count, visit_expr(p, binary.right))))
+ }
+ }
+
+ return document
}
@(private)
@@ -1494,8 +1596,9 @@ visit_call_exprs :: proc(p: ^Printer, call_expr: ^ast.Call_Expr) -> ^Document {
if i == len(call_expr.args) - 1 && ellipsis {
document = cons(document, text(".."))
}
+
document = cons(document, group(visit_expr(p, expr)))
-
+
if i != len(call_expr.args) - 1 {
document = cons(document, text(","))
@@ -1607,13 +1710,15 @@ repeat_space :: proc(amount: int) -> ^Document {
get_node_length :: proc(node: ^ast.Node) -> int {
#partial switch v in node.derived {
case ^ast.Ident:
- return len(v.name)
+ return strings.rune_count(v.name)
case ^ast.Basic_Lit:
- return len(v.tok.text)
+ return strings.rune_count(v.tok.text)
case ^ast.Implicit_Selector_Expr:
- return len(v.field.name) + 1
+ return strings.rune_count(v.field.name) + 1
case ^ast.Binary_Expr:
return 0
+ case ^ast.Selector_Expr:
+ return get_node_length(v.expr) + strings.rune_count(v.op.text) + strings.rune_count(v.field.name)
case:
panic(fmt.aprintf("unhandled get_node_length case %v", node.derived))
}
diff --git a/src/server/analysis.odin b/src/server/analysis.odin
index 8043148..933ce8a 100644
--- a/src/server/analysis.odin
+++ b/src/server/analysis.odin
@@ -1785,8 +1785,18 @@ make_symbol_union_from_ast :: proc(ast_context: ^AstContext, v: ast.Union_Type,
symbol.name = "union"
}
+ types := make([dynamic]^ast.Expr, ast_context.allocator)
+
+ for variant in v.variants {
+ if v.poly_params != nil {
+ append(&types, clone_type(variant, ast_context.allocator, nil))
+ } else {
+ append(&types, variant)
+ }
+ }
+
symbol.value = SymbolUnionValue {
- types = v.variants,
+ types = types[:],
}
if v.poly_params != nil {
diff --git a/src/server/format.odin b/src/server/format.odin
index e461044..57243ff 100644
--- a/src/server/format.odin
+++ b/src/server/format.odin
@@ -1,9 +1,10 @@
package server
import "shared:common"
-
import "shared:odin/printer"
+import "core:log"
+
FormattingOptions :: struct {
tabSize: uint,
insertSpaces: bool, //tabs or spaces
@@ -19,9 +20,16 @@ DocumentFormattingParams :: struct {
get_complete_format :: proc(document: ^Document, config: ^common.Config) -> ([]TextEdit, bool) {
style := printer.default_style
- style.max_characters = config.formatter.characters
style.tabs = config.formatter.tabs
+ if config.formatter.characters != 0 {
+ style.max_characters = config.formatter.characters
+ }
+
+ if config.formatter.spaces != 0 {
+ style.spaces = config.formatter.spaces
+ }
+
prnt := printer.make_printer(style, context.temp_allocator)
if document.ast.syntax_error_count > 0 {
@@ -34,7 +42,9 @@ get_complete_format :: proc(document: ^Document, config: ^common.Config) -> ([]T
src := printer.print(&prnt, &document.ast)
- end_line := 0
+ log.error(src)
+
+ end_line := 0
end_charcter := 0
last := document.text[0]