diff options
| author | DanielGavin <danielgavin5@hotmail.com> | 2021-03-12 16:31:09 +0100 |
|---|---|---|
| committer | DanielGavin <danielgavin5@hotmail.com> | 2021-03-12 16:31:09 +0100 |
| commit | 00ccd7e03e17dac40efb9b34a048d968dd77c218 (patch) | |
| tree | 24e9e8d9743bc3e98b63183d1f976b11ab6d93d2 /src/common | |
| parent | baf86e02a2c45170d58ab828a13f52361129b255 (diff) | |
ran odinfmt on project
Diffstat (limited to 'src/common')
| -rw-r--r-- | src/common/allocator.odin | 37 | ||||
| -rw-r--r-- | src/common/ast.odin | 1065 | ||||
| -rw-r--r-- | src/common/config.odin | 20 | ||||
| -rw-r--r-- | src/common/fuzzy.odin | 601 | ||||
| -rw-r--r-- | src/common/pool.odin | 66 | ||||
| -rw-r--r-- | src/common/position.odin | 383 | ||||
| -rw-r--r-- | src/common/pretty.odin | 454 | ||||
| -rw-r--r-- | src/common/sha1.odin | 454 | ||||
| -rw-r--r-- | src/common/track_allocator.odin | 248 | ||||
| -rw-r--r-- | src/common/types.odin | 39 | ||||
| -rw-r--r-- | src/common/uri.odin | 201 |
11 files changed, 1725 insertions, 1843 deletions
diff --git a/src/common/allocator.odin b/src/common/allocator.odin index ce96487..0adbedf 100644 --- a/src/common/allocator.odin +++ b/src/common/allocator.odin @@ -5,20 +5,20 @@ import "core:mem" Scratch_Allocator :: struct { data: []byte, curr_offset: int, - prev_allocation: rawptr, + prev_allocation: rawptr, backup_allocator: mem.Allocator, leaked_allocations: [dynamic]rawptr, } -scratch_allocator_init :: proc(s: ^Scratch_Allocator, size: int, backup_allocator := context.allocator) { - s.data = mem.make_aligned([]byte, size, 2*align_of(rawptr), backup_allocator); - s.curr_offset = 0; - s.prev_allocation = nil; - s.backup_allocator = backup_allocator; +scratch_allocator_init :: proc (s: ^Scratch_Allocator, size: int, backup_allocator := context.allocator) { + s.data = mem.make_aligned([]byte, size, 2 * align_of(rawptr), backup_allocator); + s.curr_offset = 0; + s.prev_allocation = nil; + s.backup_allocator = backup_allocator; s.leaked_allocations.allocator = backup_allocator; } -scratch_allocator_destroy :: proc(s: ^Scratch_Allocator) { +scratch_allocator_destroy :: proc (s: ^Scratch_Allocator) { if s == nil { return; } @@ -30,16 +30,16 @@ scratch_allocator_destroy :: proc(s: ^Scratch_Allocator) { s^ = {}; } -scratch_allocator_proc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode, - size, alignment: int, - old_memory: rawptr, old_size: int, flags: u64 = 0, loc := #caller_location) -> rawptr { +scratch_allocator_proc :: proc (allocator_data: rawptr, mode: mem.Allocator_Mode, +size, alignment: int, +old_memory: rawptr, old_size: int, flags: u64 = 0, loc := #caller_location) -> rawptr { s := (^Scratch_Allocator)(allocator_data); if s.data == nil { - DEFAULT_BACKING_SIZE :: 1<<22; - if !(context.allocator.procedure != scratch_allocator_proc && - context.allocator.data != allocator_data) { + DEFAULT_BACKING_SIZE :: 1 << 22; + if !(context.allocator.procedure != scratch_allocator_proc && + context.allocator.data != allocator_data) { panic("cyclic initialization of the scratch allocator with itself"); } scratch_allocator_init(s, DEFAULT_BACKING_SIZE); @@ -51,8 +51,8 @@ scratch_allocator_proc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode, case .Alloc: size = mem.align_forward_int(size, alignment); - switch { - case s.curr_offset+size <= len(s.data): + switch { + case s.curr_offset + size <= len(s.data): start := uintptr(raw_data(s.data)); ptr := start + uintptr(s.curr_offset); ptr = mem.align_forward_uintptr(ptr, uintptr(alignment)); @@ -65,7 +65,7 @@ scratch_allocator_proc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode, } a := s.backup_allocator; if a.procedure == nil { - a = context.allocator; + a = context.allocator; s.backup_allocator = a; } @@ -110,12 +110,11 @@ scratch_allocator_proc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode, return nil; } - return nil; } -scratch_allocator :: proc(allocator: ^Scratch_Allocator) -> mem.Allocator { - return mem.Allocator{ +scratch_allocator :: proc (allocator: ^Scratch_Allocator) -> mem.Allocator { + return mem.Allocator { procedure = scratch_allocator_proc, data = allocator, }; diff --git a/src/common/ast.odin b/src/common/ast.odin index d7d4890..98f2d84 100644 --- a/src/common/ast.odin +++ b/src/common/ast.odin @@ -5,633 +5,610 @@ import "core:log" import "core:mem" import "core:fmt" -keyword_map : map [string] bool = - {"int" = true, - "uint" = true, - "string" = true, - "u64" = true, - "f32" = true, - "f64" = true, - "i64" = true, - "i32" = true, - "bool" = true, - "rawptr" = true, - "any" = true, - "u32" = true, - "true" = true, - "false" = true, - "nil" = true, - "byte" = true, - "u8" = true, - "i8" = true}; - +keyword_map: map[string]bool = { + "int" = true, + "uint" = true, + "string" = true, + "u64" = true, + "f32" = true, + "f64" = true, + "i64" = true, + "i32" = true, + "bool" = true, + "rawptr" = true, + "any" = true, + "u32" = true, + "true" = true, + "false" = true, + "nil" = true, + "byte" = true, + "u8" = true, + "i8" = true, +}; GlobalExpr :: struct { - name: string, - expr: ^ast.Expr, - mutable: bool, - docs: ^ast.Comment_Group, -}; + name: string, + expr: ^ast.Expr, + mutable: bool, + docs: ^ast.Comment_Group, +} //TODO(add a sub procedure to avoid repeating the value decl work) -collect_globals :: proc(file: ast.File) -> [] GlobalExpr { - - exprs := make([dynamic] GlobalExpr, context.temp_allocator); - - for decl in file.decls { - - if value_decl, ok := decl.derived.(ast.Value_Decl); ok { - - for name, i in value_decl.names { - - str := get_ast_node_string(name, file.src); +collect_globals :: proc (file: ast.File) -> []GlobalExpr { - if value_decl.type != nil { - append(&exprs, GlobalExpr { name = str, expr = value_decl.type, mutable = value_decl.is_mutable, docs = value_decl.docs }); - } + exprs := make([dynamic]GlobalExpr, context.temp_allocator); - else { - if len(value_decl.values) > i { - append(&exprs, GlobalExpr { name = str, expr = value_decl.values[i], docs = value_decl.docs }); - } - } + for decl in file.decls { - } + if value_decl, ok := decl.derived.(ast.Value_Decl); ok { - } + for name, i in value_decl.names { - else if when_decl, ok := decl.derived.(ast.When_Stmt); ok { + str := get_ast_node_string(name, file.src); - if when_decl.cond == nil { - continue; - } + if value_decl.type != nil { + append(&exprs, GlobalExpr {name = str, expr = value_decl.type, mutable = value_decl.is_mutable, docs = value_decl.docs}); + } else { + if len(value_decl.values) > i { + append(&exprs, GlobalExpr {name = str, expr = value_decl.values[i], docs = value_decl.docs}); + } + } + } + } else if when_decl, ok := decl.derived.(ast.When_Stmt); ok { - if when_decl.body == nil { - continue; - } + if when_decl.cond == nil { + continue; + } - if binary, ok := when_decl.cond.derived.(ast.Binary_Expr); ok { + if when_decl.body == nil { + continue; + } - if binary.left == nil || binary.right == nil { - continue; - } + if binary, ok := when_decl.cond.derived.(ast.Binary_Expr); ok { - ident: ^ast.Ident; - basic_lit: ^ast.Basic_Lit; + if binary.left == nil || binary.right == nil { + continue; + } - if t, ok := binary.left.derived.(ast.Ident); ok { - ident = cast(^ast.Ident)binary.left; - } + ident: ^ast.Ident; + basic_lit: ^ast.Basic_Lit; - else if t, ok := binary.left.derived.(ast.Basic_Lit); ok { - basic_lit = cast(^ast.Basic_Lit)binary.left; - } + if t, ok := binary.left.derived.(ast.Ident); ok { + ident = cast(^ast.Ident)binary.left; + } else if t, ok := binary.left.derived.(ast.Basic_Lit); ok { + basic_lit = cast(^ast.Basic_Lit)binary.left; + } - if t, ok := binary.right.derived.(ast.Ident); ok { - ident = cast(^ast.Ident)binary.right; - } + if t, ok := binary.right.derived.(ast.Ident); ok { + ident = cast(^ast.Ident)binary.right; + } else if t, ok := binary.right.derived.(ast.Basic_Lit); ok { + basic_lit = cast(^ast.Basic_Lit)binary.right; + } - else if t, ok := binary.right.derived.(ast.Basic_Lit); ok { - basic_lit = cast(^ast.Basic_Lit)binary.right; - } + if ident != nil && basic_lit != nil { - if ident != nil && basic_lit != nil { + //hardcode for windows for now + if ident.name == "ODIN_OS" && basic_lit.tok.text == "\"windows\"" { - //hardcode for windows for now - if ident.name == "ODIN_OS" && basic_lit.tok.text == "\"windows\"" { + log.errorf("when %v %v", ident, basic_lit); - log.errorf("when %v %v", ident, basic_lit); + if block, ok := when_decl.body.derived.(ast.Block_Stmt); ok { - if block, ok := when_decl.body.derived.(ast.Block_Stmt); ok { + for stmt in block.stmts { - for stmt in block.stmts { + if value_decl, ok := stmt.derived.(ast.Value_Decl); ok { - if value_decl, ok := stmt.derived.(ast.Value_Decl); ok { + for name, i in value_decl.names { - for name, i in value_decl.names { + str := get_ast_node_string(name, file.src); - str := get_ast_node_string(name, file.src); + if value_decl.type != nil { + append(&exprs, GlobalExpr {name = str, expr = value_decl.type, mutable = value_decl.is_mutable, docs = value_decl.docs}); + } else { + if len(value_decl.values) > i { + append(&exprs, GlobalExpr {name = str, expr = value_decl.values[i], docs = value_decl.docs}); + } + } + } + } + } + } + } + } + } + //YUPPI - what a fun slide - if value_decl.type != nil { - append(&exprs, GlobalExpr { name = str, expr = value_decl.type, mutable = value_decl.is_mutable, docs = value_decl.docs }); - } + } else if foreign_decl, ok := decl.derived.(ast.Foreign_Block_Decl); ok { - else { - if len(value_decl.values) > i { - append(&exprs, GlobalExpr { name = str, expr = value_decl.values[i], docs = value_decl.docs }); - } - } - } - } - } - } - } - } - } - //YUPPI - what a fun slide + if foreign_decl.body == nil { + continue; + } - } + if block, ok := foreign_decl.body.derived.(ast.Block_Stmt); ok { - else if foreign_decl, ok := decl.derived.(ast.Foreign_Block_Decl); ok { + for stmt in block.stmts { - if foreign_decl.body == nil { - continue; - } + if value_decl, ok := stmt.derived.(ast.Value_Decl); ok { - if block, ok := foreign_decl.body.derived.(ast.Block_Stmt); ok { + for name, i in value_decl.names { - for stmt in block.stmts { + str := get_ast_node_string(name, file.src); - if value_decl, ok := stmt.derived.(ast.Value_Decl); ok { - - for name, i in value_decl.names { - - str := get_ast_node_string(name, file.src); - - if value_decl.type != nil { - append(&exprs, GlobalExpr { name = str, expr = value_decl.type, mutable = value_decl.is_mutable, docs = value_decl.docs }); - } - - else { - if len(value_decl.values) > i { - append(&exprs, GlobalExpr { name = str, expr = value_decl.values[i], docs = value_decl.docs }); - } - } - } - } - } - } - } - } + if value_decl.type != nil { + append(&exprs, GlobalExpr {name = str, expr = value_decl.type, mutable = value_decl.is_mutable, docs = value_decl.docs}); + } else { + if len(value_decl.values) > i { + append(&exprs, GlobalExpr {name = str, expr = value_decl.values[i], docs = value_decl.docs}); + } + } + } + } + } + } + } + } - return exprs[:]; + return exprs[:]; } - -get_ast_node_string :: proc(node: ^ast.Node, src: [] byte) -> string { - return string(src[node.pos.offset:node.end.offset]); +get_ast_node_string :: proc (node: ^ast.Node, src: []byte) -> string { + return string(src[node.pos.offset:node.end.offset]); } -free_ast :: proc{ - free_ast_node, - free_ast_array, - free_ast_dynamic_array, - free_ast_comment, -}; +free_ast :: proc { +free_ast_node, +free_ast_array, +free_ast_dynamic_array, +free_ast_comment}; -free_ast_comment :: proc(a: ^ast.Comment_Group, allocator: mem.Allocator) { - if a == nil { - return; - } +free_ast_comment :: proc (a: ^ast.Comment_Group, allocator: mem.Allocator) { + if a == nil { + return; + } - if len(a.list) > 0 { - delete(a.list, allocator); - } + if len(a.list) > 0 { + delete(a.list, allocator); + } - free(a, allocator); + free(a, allocator); } -free_ast_array :: proc(array: $A/[]^$T, allocator: mem.Allocator) { +free_ast_array :: proc (array: $A/[]^$T, allocator: mem.Allocator) { for elem, i in array { free_ast(elem, allocator); } - delete(array, allocator); + delete(array, allocator); } -free_ast_dynamic_array :: proc(array: $A/[dynamic]^$T, allocator: mem.Allocator) { +free_ast_dynamic_array :: proc (array: $A/[dynamic]^$T, allocator: mem.Allocator) { for elem, i in array { free_ast(elem, allocator); } - delete(array); + delete(array); } -free_ast_node :: proc(node: ^ast.Node, allocator: mem.Allocator) { - - using ast; - - if node == nil { - return; - } - - switch n in node.derived { - case Bad_Expr: - case Ident: - case Implicit: - case Undef: - case Basic_Directive: - case Basic_Lit: - case Ellipsis: - free_ast(n.expr, allocator); - case Proc_Lit: - free_ast(n.type, allocator); - free_ast(n.body, allocator); - free_ast(n.where_clauses, allocator); - case Comp_Lit: - free_ast(n.type, allocator); - free_ast(n.elems, allocator); - case Tag_Expr: - free_ast(n.expr, allocator); - case Unary_Expr: - free_ast(n.expr, allocator); - case Binary_Expr: - free_ast(n.left, allocator); - free_ast(n.right, allocator); - case Paren_Expr: - free_ast(n.expr, allocator); - case Call_Expr: - free_ast(n.expr, allocator); - free_ast(n.args, allocator); - case Selector_Expr: - free_ast(n.expr, allocator); - free_ast(n.field, allocator); - case Implicit_Selector_Expr: - free_ast(n.field, allocator); - case Index_Expr: - free_ast(n.expr, allocator); - free_ast(n.index, allocator); - case Deref_Expr: - free_ast(n.expr, allocator); - case Slice_Expr: - free_ast(n.expr, allocator); - free_ast(n.low, allocator); - free_ast(n.high, allocator); - case Field_Value: - free_ast(n.field, allocator); - free_ast(n.value, allocator); - case Ternary_Expr: - free_ast(n.cond, allocator); - free_ast(n.x, allocator); - free_ast(n.y, allocator); - case Ternary_If_Expr: - free_ast(n.x, allocator); - free_ast(n.cond, allocator); - free_ast(n.y, allocator); - case Ternary_When_Expr: - free_ast(n.x, allocator); - free_ast(n.cond, allocator); - free_ast(n.y, allocator); - case Type_Assertion: - free_ast(n.expr, allocator); - free_ast(n.type, allocator); - case Type_Cast: - free_ast(n.type, allocator); - free_ast(n.expr, allocator); - case Auto_Cast: - free_ast(n.expr, allocator); - case Bad_Stmt: - case Empty_Stmt: - case Expr_Stmt: - free_ast(n.expr, allocator); - case Tag_Stmt: - r := cast(^Expr_Stmt)node; - free_ast(r.expr, allocator); - case Assign_Stmt: - free_ast(n.lhs, allocator); - free_ast(n.rhs, allocator); - case Block_Stmt: - free_ast(n.label, allocator); - free_ast(n.stmts, allocator); - case If_Stmt: - free_ast(n.label, allocator); - free_ast(n.init, allocator); - free_ast(n.cond, allocator); - free_ast(n.body, allocator); - free_ast(n.else_stmt, allocator); - case When_Stmt: - free_ast(n.cond, allocator); - free_ast(n.body, allocator); - free_ast(n.else_stmt, allocator); - case Return_Stmt: - free_ast(n.results, allocator); - case Defer_Stmt: - free_ast(n.stmt, allocator); - case For_Stmt: - free_ast(n.label, allocator); - free_ast(n.init, allocator); - free_ast(n.cond, allocator); - free_ast(n.post, allocator); - free_ast(n.body, allocator); - case Range_Stmt: - free_ast(n.label, allocator); - free_ast(n.val0, allocator); - free_ast(n.val1, allocator); - free_ast(n.expr, allocator); - free_ast(n.body, allocator); - case Case_Clause: - free_ast(n.list, allocator); - free_ast(n.body, allocator); - case Switch_Stmt: - free_ast(n.label, allocator); - free_ast(n.init, allocator); - free_ast(n.cond, allocator); - free_ast(n.body, allocator); - case Type_Switch_Stmt: - free_ast(n.label, allocator); - free_ast(n.tag, allocator); - free_ast(n.expr, allocator); - free_ast(n.body, allocator); - case Branch_Stmt: - free_ast(n.label, allocator); - case Using_Stmt: - free_ast(n.list, allocator); - case Bad_Decl: - case Value_Decl: - free_ast(n.attributes, allocator); - free_ast(n.names, allocator); - free_ast(n.type, allocator); - free_ast(n.values, allocator); - //free_ast(n.docs); - //free_ast(n.comment); - case Package_Decl: - //free_ast(n.docs); - //free_ast(n.comment); - case Import_Decl: - //free_ast(n.docs); - //free_ast(n.comment); - case Foreign_Block_Decl: - free_ast(n.attributes, allocator); - free_ast(n.foreign_library, allocator); - free_ast(n.body, allocator); - case Foreign_Import_Decl: - free_ast(n.name, allocator); - free_ast(n.attributes, allocator); - case Proc_Group: - free_ast(n.args, allocator); - case Attribute: - free_ast(n.elems, allocator); - case Field: - free_ast(n.names, allocator); - free_ast(n.type, allocator); - free_ast(n.default_value, allocator); - //free_ast(n.docs); - //free_ast(n.comment); - case Field_List: - free_ast(n.list, allocator); - case Typeid_Type: - free_ast(n.specialization, allocator); - case Helper_Type: - free_ast(n.type, allocator); - case Distinct_Type: - free_ast(n.type, allocator); - case Poly_Type: - free_ast(n.type, allocator); - free_ast(n.specialization, allocator); - case Proc_Type: - free_ast(n.params, allocator); - free_ast(n.results, allocator); - case Pointer_Type: - free_ast(n.elem, allocator); - case Array_Type: - free_ast(n.len, allocator); - free_ast(n.elem, allocator); - free_ast(n.tag, allocator); - case Dynamic_Array_Type: - free_ast(n.elem, allocator); - free_ast(n.tag, allocator); - case Struct_Type: - free_ast(n.poly_params, allocator); - free_ast(n.align, allocator); - free_ast(n.fields, allocator); - free_ast(n.where_clauses, allocator); - case Union_Type: - free_ast(n.poly_params, allocator); - free_ast(n.align, allocator); - free_ast(n.variants, allocator); - free_ast(n.where_clauses, allocator); - case Enum_Type: - free_ast(n.base_type, allocator); - free_ast(n.fields, allocator); - case Bit_Set_Type: - free_ast(n.elem, allocator); - free_ast(n.underlying, allocator); - case Map_Type: - free_ast(n.key, allocator); - free_ast(n.value, allocator); - case: - log.warnf("free Unhandled node kind: %T", n); - } - - mem.free(node, allocator); -} +free_ast_node :: proc (node: ^ast.Node, allocator: mem.Allocator) { + using ast; + if node == nil { + return; + } -free_ast_file :: proc(file: ast.File, allocator := context.allocator) { + switch n in node.derived { + case Bad_Expr: + case Ident: + case Implicit: + case Undef: + case Basic_Directive: + case Basic_Lit: + case Ellipsis: + free_ast(n.expr, allocator); + case Proc_Lit: + free_ast(n.type, allocator); + free_ast(n.body, allocator); + free_ast(n.where_clauses, allocator); + case Comp_Lit: + free_ast(n.type, allocator); + free_ast(n.elems, allocator); + case Tag_Expr: + free_ast(n.expr, allocator); + case Unary_Expr: + free_ast(n.expr, allocator); + case Binary_Expr: + free_ast(n.left, allocator); + free_ast(n.right, allocator); + case Paren_Expr: + free_ast(n.expr, allocator); + case Call_Expr: + free_ast(n.expr, allocator); + free_ast(n.args, allocator); + case Selector_Expr: + free_ast(n.expr, allocator); + free_ast(n.field, allocator); + case Implicit_Selector_Expr: + free_ast(n.field, allocator); + case Index_Expr: + free_ast(n.expr, allocator); + free_ast(n.index, allocator); + case Deref_Expr: + free_ast(n.expr, allocator); + case Slice_Expr: + free_ast(n.expr, allocator); + free_ast(n.low, allocator); + free_ast(n.high, allocator); + case Field_Value: + free_ast(n.field, allocator); + free_ast(n.value, allocator); + case Ternary_Expr: + free_ast(n.cond, allocator); + free_ast(n.x, allocator); + free_ast(n.y, allocator); + case Ternary_If_Expr: + free_ast(n.x, allocator); + free_ast(n.cond, allocator); + free_ast(n.y, allocator); + case Ternary_When_Expr: + free_ast(n.x, allocator); + free_ast(n.cond, allocator); + free_ast(n.y, allocator); + case Type_Assertion: + free_ast(n.expr, allocator); + free_ast(n.type, allocator); + case Type_Cast: + free_ast(n.type, allocator); + free_ast(n.expr, allocator); + case Auto_Cast: + free_ast(n.expr, allocator); + case Bad_Stmt: + case Empty_Stmt: + case Expr_Stmt: + free_ast(n.expr, allocator); + case Tag_Stmt: + r := cast(^Expr_Stmt)node; + free_ast(r.expr, allocator); + case Assign_Stmt: + free_ast(n.lhs, allocator); + free_ast(n.rhs, allocator); + case Block_Stmt: + free_ast(n.label, allocator); + free_ast(n.stmts, allocator); + case If_Stmt: + free_ast(n.label, allocator); + free_ast(n.init, allocator); + free_ast(n.cond, allocator); + free_ast(n.body, allocator); + free_ast(n.else_stmt, allocator); + case When_Stmt: + free_ast(n.cond, allocator); + free_ast(n.body, allocator); + free_ast(n.else_stmt, allocator); + case Return_Stmt: + free_ast(n.results, allocator); + case Defer_Stmt: + free_ast(n.stmt, allocator); + case For_Stmt: + free_ast(n.label, allocator); + free_ast(n.init, allocator); + free_ast(n.cond, allocator); + free_ast(n.post, allocator); + free_ast(n.body, allocator); + case Range_Stmt: + free_ast(n.label, allocator); + free_ast(n.val0, allocator); + free_ast(n.val1, allocator); + free_ast(n.expr, allocator); + free_ast(n.body, allocator); + case Case_Clause: + free_ast(n.list, allocator); + free_ast(n.body, allocator); + case Switch_Stmt: + free_ast(n.label, allocator); + free_ast(n.init, allocator); + free_ast(n.cond, allocator); + free_ast(n.body, allocator); + case Type_Switch_Stmt: + free_ast(n.label, allocator); + free_ast(n.tag, allocator); + free_ast(n.expr, allocator); + free_ast(n.body, allocator); + case Branch_Stmt: + free_ast(n.label, allocator); + case Using_Stmt: + free_ast(n.list, allocator); + case Bad_Decl: + case Value_Decl: + free_ast(n.attributes, allocator); + free_ast(n.names, allocator); + free_ast(n.type, allocator); + free_ast(n.values, allocator); + //free_ast(n.docs); + //free_ast(n.comment); + case Package_Decl: + //free_ast(n.docs); + //free_ast(n.comment); + case Import_Decl: + //free_ast(n.docs); + //free_ast(n.comment); + case Foreign_Block_Decl: + free_ast(n.attributes, allocator); + free_ast(n.foreign_library, allocator); + free_ast(n.body, allocator); + case Foreign_Import_Decl: + free_ast(n.name, allocator); + free_ast(n.attributes, allocator); + case Proc_Group: + free_ast(n.args, allocator); + case Attribute: + free_ast(n.elems, allocator); + case Field: + free_ast(n.names, allocator); + free_ast(n.type, allocator); + free_ast(n.default_value, allocator); + //free_ast(n.docs); + //free_ast(n.comment); + case Field_List: + free_ast(n.list, allocator); + case Typeid_Type: + free_ast(n.specialization, allocator); + case Helper_Type: + free_ast(n.type, allocator); + case Distinct_Type: + free_ast(n.type, allocator); + case Poly_Type: + free_ast(n.type, allocator); + free_ast(n.specialization, allocator); + case Proc_Type: + free_ast(n.params, allocator); + free_ast(n.results, allocator); + case Pointer_Type: + free_ast(n.elem, allocator); + case Array_Type: + free_ast(n.len, allocator); + free_ast(n.elem, allocator); + free_ast(n.tag, allocator); + case Dynamic_Array_Type: + free_ast(n.elem, allocator); + free_ast(n.tag, allocator); + case Struct_Type: + free_ast(n.poly_params, allocator); + free_ast(n.align, allocator); + free_ast(n.fields, allocator); + free_ast(n.where_clauses, allocator); + case Union_Type: + free_ast(n.poly_params, allocator); + free_ast(n.align, allocator); + free_ast(n.variants, allocator); + free_ast(n.where_clauses, allocator); + case Enum_Type: + free_ast(n.base_type, allocator); + free_ast(n.fields, allocator); + case Bit_Set_Type: + free_ast(n.elem, allocator); + free_ast(n.underlying, allocator); + case Map_Type: + free_ast(n.key, allocator); + free_ast(n.value, allocator); + case: + log.warnf("free Unhandled node kind: %T", n); + } - for decl in file.decls { - free_ast(decl, allocator); - } + mem.free(node, allocator); +} - free_ast(file.pkg_decl, allocator); +free_ast_file :: proc (file: ast.File, allocator := context.allocator) { - for comment in file.comments { - free_ast(comment, allocator); - } + for decl in file.decls { + free_ast(decl, allocator); + } - delete(file.comments); - delete(file.imports); - delete(file.decls); -} + free_ast(file.pkg_decl, allocator); + for comment in file.comments { + free_ast(comment, allocator); + } -node_equal :: proc{ - node_equal_node, - node_equal_array, - node_equal_dynamic_array -}; + delete(file.comments); + delete(file.imports); + delete(file.decls); +} + +node_equal :: proc { +node_equal_node, +node_equal_array, +node_equal_dynamic_array}; -node_equal_array :: proc(a, b: $A/[]^$T) -> bool { +node_equal_array :: proc (a, b: $A/[]^$T) -> bool { - ret := true; + ret := true; - if len(a) != len(b) { - return false; - } + if len(a) != len(b) { + return false; + } for elem, i in a { ret &= node_equal(elem, b[i]); } - return ret; + return ret; } -node_equal_dynamic_array :: proc(a, b: $A/[dynamic]^$T) -> bool { +node_equal_dynamic_array :: proc (a, b: $A/[dynamic]^$T) -> bool { - ret := true; + ret := true; - if len(a) != len(b) { - return false; - } + if len(a) != len(b) { + return false; + } for elem, i in a { ret &= node_equal(elem, b[i]); } - return ret; + return ret; } +node_equal_node :: proc (a, b: ^ast.Node) -> bool { + + using ast; -node_equal_node :: proc(a, b: ^ast.Node) -> bool { - - using ast; - - if a == nil || b == nil { - return false; - } - - switch m in b.derived { - case Bad_Expr: - if n, ok := a.derived.(Bad_Expr); ok { - return true; - } - case Ident: - if n, ok := a.derived.(Ident); ok { - return true; - //return n.name == m.name; - } - case Implicit: - if n, ok := a.derived.(Implicit); ok { - return true; - } - case Undef: - if n, ok := a.derived.(Undef); ok { - return true; - } - case Basic_Lit: - if n, ok := a.derived.(Basic_Lit); ok { - return true; - } - case Poly_Type: - return true; - //return node_equal(n.sp) - //if n, ok := a.derived.(Poly_Type); ok { - // ret := node_equal(n.type, m.type); - // ret &= node_equal(n.specialization, m.specialization); - // return ret; - //} - case Ellipsis: - if n, ok := a.derived.(Ellipsis); ok { - return node_equal(n.expr, m.expr); - } - case Tag_Expr: - if n, ok := a.derived.(Tag_Expr); ok { - return node_equal(n.expr, m.expr); - } - case Unary_Expr: - if n, ok := a.derived.(Unary_Expr); ok { - return node_equal(n.expr, m.expr); - } - case Binary_Expr: - if n, ok := a.derived.(Binary_Expr); ok { - ret := node_equal(n.left, m.left); - ret &= node_equal(n.right, m.right); - return ret; - } - case Paren_Expr: - if n, ok := a.derived.(Paren_Expr); ok { - return node_equal(n.expr, m.expr); - } - case Selector_Expr: - if n, ok := a.derived.(Selector_Expr); ok { - ret := node_equal(n.expr, m.expr); - ret &= node_equal(n.field, m.field); - return ret; - } - case Slice_Expr: - if n, ok := a.derived.(Slice_Expr); ok { - ret := node_equal(n.expr, m.expr); - ret &= node_equal(n.low, m.low); - ret &= node_equal(n.high, m.high); - return ret; - } - case Distinct_Type: - if n, ok := a.derived.(Distinct_Type); ok { - return node_equal(n.type, m.type); - } - case Proc_Type: - if n, ok := a.derived.(Proc_Type); ok { - ret := node_equal(n.params, m.params); - ret &= node_equal(n.results, m.results); - return ret; - } - case Pointer_Type: - if n, ok := a.derived.(Pointer_Type); ok { - return node_equal(n.elem, m.elem); - } - case Array_Type: - if n, ok := a.derived.(Array_Type); ok { - ret := node_equal(n.len, m.len); - ret &= node_equal(n.elem, m.elem); - return ret; - } - case Dynamic_Array_Type: - if n, ok := a.derived.(Dynamic_Array_Type); ok { - return node_equal(n.elem, m.elem); - } - case Struct_Type: - if n, ok := a.derived.(Struct_Type); ok { - ret := node_equal(n.poly_params, m.poly_params); - ret &= node_equal(n.align, m.align); - ret &= node_equal(n.fields, m.fields); - return ret; - } - case Field: - if n, ok := a.derived.(Field); ok { - ret := node_equal(n.names, m.names); - ret &= node_equal(n.type, m.type); - ret &= node_equal(n.default_value, m.default_value); - return ret; - } + if a == nil || b == nil { + return false; + } + + switch m in b.derived { + case Bad_Expr: + if n, ok := a.derived.(Bad_Expr); ok { + return true; + } + case Ident: + if n, ok := a.derived.(Ident); ok { + return true; + //return n.name == m.name; + } + case Implicit: + if n, ok := a.derived.(Implicit); ok { + return true; + } + case Undef: + if n, ok := a.derived.(Undef); ok { + return true; + } + case Basic_Lit: + if n, ok := a.derived.(Basic_Lit); ok { + return true; + } + case Poly_Type: + return true; + //return node_equal(n.sp) + //if n, ok := a.derived.(Poly_Type); ok { + // ret := node_equal(n.type, m.type); + // ret &= node_equal(n.specialization, m.specialization); + // return ret; + //} + case Ellipsis: + if n, ok := a.derived.(Ellipsis); ok { + return node_equal(n.expr, m.expr); + } + case Tag_Expr: + if n, ok := a.derived.(Tag_Expr); ok { + return node_equal(n.expr, m.expr); + } + case Unary_Expr: + if n, ok := a.derived.(Unary_Expr); ok { + return node_equal(n.expr, m.expr); + } + case Binary_Expr: + if n, ok := a.derived.(Binary_Expr); ok { + ret := node_equal(n.left, m.left); + ret &= node_equal(n.right, m.right); + return ret; + } + case Paren_Expr: + if n, ok := a.derived.(Paren_Expr); ok { + return node_equal(n.expr, m.expr); + } + case Selector_Expr: + if n, ok := a.derived.(Selector_Expr); ok { + ret := node_equal(n.expr, m.expr); + ret &= node_equal(n.field, m.field); + return ret; + } + case Slice_Expr: + if n, ok := a.derived.(Slice_Expr); ok { + ret := node_equal(n.expr, m.expr); + ret &= node_equal(n.low, m.low); + ret &= node_equal(n.high, m.high); + return ret; + } + case Distinct_Type: + if n, ok := a.derived.(Distinct_Type); ok { + return node_equal(n.type, m.type); + } + case Proc_Type: + if n, ok := a.derived.(Proc_Type); ok { + ret := node_equal(n.params, m.params); + ret &= node_equal(n.results, m.results); + return ret; + } + case Pointer_Type: + if n, ok := a.derived.(Pointer_Type); ok { + return node_equal(n.elem, m.elem); + } + case Array_Type: + if n, ok := a.derived.(Array_Type); ok { + ret := node_equal(n.len, m.len); + ret &= node_equal(n.elem, m.elem); + return ret; + } + case Dynamic_Array_Type: + if n, ok := a.derived.(Dynamic_Array_Type); ok { + return node_equal(n.elem, m.elem); + } + case Struct_Type: + if n, ok := a.derived.(Struct_Type); ok { + ret := node_equal(n.poly_params, m.poly_params); + ret &= node_equal(n.align, m.align); + ret &= node_equal(n.fields, m.fields); + return ret; + } + case Field: + if n, ok := a.derived.(Field); ok { + ret := node_equal(n.names, m.names); + ret &= node_equal(n.type, m.type); + ret &= node_equal(n.default_value, m.default_value); + return ret; + } case Field_List: - if n, ok := a.derived.(Field_List); ok { - return node_equal(n.list, m.list); - } - case Field_Value: - if n, ok := a.derived.(Field_Value); ok { - ret := node_equal(n.field, m.field); - ret &= node_equal(n.value, m.value); - return ret; - } - case Union_Type: - if n, ok := a.derived.(Union_Type); ok { - ret := node_equal(n.poly_params, m.poly_params); - ret &= node_equal(n.align, m.align); - ret &= node_equal(n.variants, m.variants); - return ret; - } - case Enum_Type: - if n, ok := a.derived.(Enum_Type); ok { - ret := node_equal(n.base_type, m.base_type); - ret &= node_equal(n.fields, m.fields); - return ret; - } - case Bit_Set_Type: - if n, ok := a.derived.(Bit_Set_Type); ok { - ret := node_equal(n.elem, m.elem); - ret &= node_equal(n.underlying, m.underlying); - return ret; - } - case Map_Type: - if n, ok := a.derived.(Map_Type); ok { - ret := node_equal(n.key, m.key); - ret &= node_equal(n.value, m.value); - return ret; - } - case Call_Expr: - if n, ok := a.derived.(Call_Expr); ok { - ret := node_equal(n.expr, m.expr); - ret &= node_equal(n.args, m.args); - return ret; - } - case Typeid_Type: - return true; - //if n, ok := a.derived.(Typeid_Type); ok { - // return node_equal(n.specialization, m.specialization); - //} - case: - log.warn("Unhandled poly node kind: %T", m); - } - - return false; + if n, ok := a.derived.(Field_List); ok { + return node_equal(n.list, m.list); + } + case Field_Value: + if n, ok := a.derived.(Field_Value); ok { + ret := node_equal(n.field, m.field); + ret &= node_equal(n.value, m.value); + return ret; + } + case Union_Type: + if n, ok := a.derived.(Union_Type); ok { + ret := node_equal(n.poly_params, m.poly_params); + ret &= node_equal(n.align, m.align); + ret &= node_equal(n.variants, m.variants); + return ret; + } + case Enum_Type: + if n, ok := a.derived.(Enum_Type); ok { + ret := node_equal(n.base_type, m.base_type); + ret &= node_equal(n.fields, m.fields); + return ret; + } + case Bit_Set_Type: + if n, ok := a.derived.(Bit_Set_Type); ok { + ret := node_equal(n.elem, m.elem); + ret &= node_equal(n.underlying, m.underlying); + return ret; + } + case Map_Type: + if n, ok := a.derived.(Map_Type); ok { + ret := node_equal(n.key, m.key); + ret &= node_equal(n.value, m.value); + return ret; + } + case Call_Expr: + if n, ok := a.derived.(Call_Expr); ok { + ret := node_equal(n.expr, m.expr); + ret &= node_equal(n.args, m.args); + return ret; + } + case Typeid_Type: + return true; + //if n, ok := a.derived.(Typeid_Type); ok { + // return node_equal(n.specialization, m.specialization); + //} + case: + log.warn("Unhandled poly node kind: %T", m); + } + + return false; }
\ No newline at end of file diff --git a/src/common/config.odin b/src/common/config.odin index 12ae171..ddf4d2a 100644 --- a/src/common/config.odin +++ b/src/common/config.odin @@ -1,13 +1,13 @@ package common Config :: struct { - workspace_folders: [dynamic] WorkspaceFolder, - completion_support_md: bool, - hover_support_md: bool, - signature_offset_support: bool, - collections: map [string] string, - running: bool, - verbose: bool, - debug_single_thread: bool, - enable_semantic_tokens: bool, //This will be removed when vscode client stops sending me semantic tokens after disabling it in requests initialize. -};
\ No newline at end of file + workspace_folders: [dynamic]WorkspaceFolder, + completion_support_md: bool, + hover_support_md: bool, + signature_offset_support: bool, + collections: map[string]string, + running: bool, + verbose: bool, + debug_single_thread: bool, + enable_semantic_tokens: bool, //This will be removed when vscode client stops sending me semantic tokens after disabling it in requests initialize. +}
\ No newline at end of file diff --git a/src/common/fuzzy.odin b/src/common/fuzzy.odin index c582421..f0b4a82 100644 --- a/src/common/fuzzy.odin +++ b/src/common/fuzzy.odin @@ -4,430 +4,413 @@ import "core:strings" import "core:fmt" /* - Ported from https://github.com/llvm/llvm-project/blob/master/clang-tools-extra/clangd/FuzzyMatch.cpp + Ported from https://github.com/llvm/llvm-project/blob/master/clang-tools-extra/clangd/FuzzyMatch.cpp */ max_pattern :: 63; -max_word :: 127; +max_word :: 127; awful_score: int = -(1 << 13); perfect_bonus :: 4; -miss :: 0; -match :: 1; +miss :: 0; +match :: 1; FuzzyCharTypeSet :: u8; - - //do bitfield instead FuzzyScoreInfo :: struct { - score: int, - prev: int, -}; - - + score: int, + prev: int, +} -FuzzyCharRole :: enum(u8) { - Unknown = 0, // Stray control characters or impossible states. - Tail = 1, // Part of a word segment, but not the first character. - Head = 2, // The first character of a word segment. - Separator = 3, // Punctuation characters that separate word segments. -}; +FuzzyCharRole :: enum (u8) +// Stray control characters or impossible states. +// Part of a word segment, but not the first character. +// The first character of a word segment. +{ + Unknown = 0, + Tail = 1, + Head = 2, + Separator = 3, // Punctuation characters that separate word segments. +} -FuzzyCharType :: enum(u8) { - Empty = 0, // Before-the-start and after-the-end (and control chars). - Lower = 1, // Lowercase letters, digits, and non-ASCII bytes. - Upper = 2, // Uppercase letters. - Punctuation = 3, // ASCII punctuation (including Space) -}; +FuzzyCharType :: enum (u8) +// Before-the-start and after-the-end (and control chars). +// Lowercase letters, digits, and non-ASCII bytes. +// Uppercase letters. +{ + Empty = 0, + Lower = 1, + Upper = 2, + Punctuation = 3, // ASCII punctuation (including Space) +} FuzzyMatcher :: struct { - pattern: string, - word: string, - lower_pattern: string, - lower_word: string, - scores: [max_pattern + 1][max_word + 1][2] FuzzyScoreInfo, - pattern_count: int, - pattern_type_set: FuzzyCharTypeSet, - word_type_set: FuzzyCharTypeSet, - pattern_role: [max_pattern] FuzzyCharRole, - word_count: int, - score_scale: f32, - word_role: [max_word] FuzzyCharRole, -}; - + pattern: string, + word: string, + lower_pattern: string, + lower_word: string, + scores: [max_pattern + 1][max_word + 1][2]FuzzyScoreInfo, + pattern_count: int, + pattern_type_set: FuzzyCharTypeSet, + word_type_set: FuzzyCharTypeSet, + pattern_role: [max_pattern]FuzzyCharRole, + word_count: int, + score_scale: f32, + word_role: [max_word]FuzzyCharRole, +} -char_roles : [] u8 = { - // clang-format off - // Curr= Empty Lower Upper Separ - /* Prev=Empty */ 0x00, 0xaa, 0xaa, 0xff, // At start, Lower|Upper->Head - /* Prev=Lower */ 0x00, 0x55, 0xaa, 0xff, // In word, Upper->Head;Lower->Tail - /* Prev=Upper */ 0x00, 0x55, 0x59, 0xff, // Ditto, but U(U)U->Tail - /* Prev=Separ */ 0x00, 0xaa, 0xaa, 0xff, // After separator, like at start - // clang-format on +char_roles: []u8 = +// clang-format off +// Curr= Empty Lower Upper Separ +/*Prev=Empty */{ + 0x00,0xaa,0xaa,0xff, // At start, Lower|Upper->Head + /*Prev=Lower */0x00,0x55,0xaa,0xff, // In word, Upper->Head;Lower->Tail + /*Prev=Upper */0x00,0x55,0x59,0xff, // Ditto, but U(U)U->Tail + /*Prev=Separ */0x00,0xaa,0xaa,0xff, // After separator, like at start + // clang-format on }; -char_types : [] u8 = { - 0x00, 0x00, 0x00, 0x00, // Control characters - 0x00, 0x00, 0x00, 0x00, // Control characters - 0xff, 0xff, 0xff, 0xff, // Punctuation - 0x55, 0x55, 0xf5, 0xff, // Numbers->Lower, more Punctuation. - 0xab, 0xaa, 0xaa, 0xaa, // @ and A-O - 0xaa, 0xaa, 0xea, 0xff, // P-Z, more Punctuation. - 0x57, 0x55, 0x55, 0x55, // ` and a-o - 0x55, 0x55, 0xd5, 0x3f, // p-z, Punctuation, DEL. - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, // Bytes over 127 -> Lower. - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, // (probably UTF-8). - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, +char_types: []u8 = { + 0x00,0x00,0x00,0x00, // Control characters + 0x00,0x00,0x00,0x00, // Control characters + 0xff,0xff,0xff,0xff, // Punctuation + 0x55,0x55,0xf5,0xff, // Numbers->Lower, more Punctuation. + 0xab,0xaa,0xaa,0xaa, // @ and A-O + 0xaa,0xaa,0xea,0xff, // P-Z, more Punctuation. + 0x57,0x55,0x55,0x55, // ` and a-o + 0x55,0x55,0xd5,0x3f, // p-z, Punctuation, DEL. + 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55, // Bytes over 127 -> Lower. + 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55, // (probably UTF-8). + 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55, + 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55, }; - make_fuzzy_matcher :: proc (pattern: string, allocator := context.temp_allocator) -> ^FuzzyMatcher { - matcher := new(FuzzyMatcher, allocator); - - matcher.pattern_count = min(len(pattern), max_pattern); - matcher.score_scale = matcher.pattern_count > 0 ? 1 / cast(f32)(perfect_bonus * matcher.pattern_count) : 0; - matcher.pattern = pattern[0:matcher.pattern_count]; - matcher.lower_pattern = strings.to_lower(matcher.pattern, context.temp_allocator); + matcher := new(FuzzyMatcher, allocator); - score_info_miss: FuzzyScoreInfo; - score_info_miss.score = 0; - score_info_miss.prev = miss; + matcher.pattern_count = min(len(pattern), max_pattern); + matcher.score_scale = matcher.pattern_count > 0 ? 1 / cast(f32)(perfect_bonus * matcher.pattern_count) : 0; + matcher.pattern = pattern[0:matcher.pattern_count]; + matcher.lower_pattern = strings.to_lower(matcher.pattern, context.temp_allocator); - matcher.scores[0][0][miss] = score_info_miss; + score_info_miss: FuzzyScoreInfo; + score_info_miss.score = 0; + score_info_miss.prev = miss; - score_info_match: FuzzyScoreInfo; - score_info_match.score = awful_score; - score_info_match.prev = match; + matcher.scores[0][0][miss] = score_info_miss; - matcher.scores[0][0][match] = score_info_match; + score_info_match: FuzzyScoreInfo; + score_info_match.score = awful_score; + score_info_match.prev = match; - for p := 0; p < matcher.pattern_count; p += 1 { + matcher.scores[0][0][match] = score_info_match; - for w := 0; w < p; w+= 1 { + for p := 0; p < matcher.pattern_count; p += 1 { - for a := 0; a < 2; a += 1 { - score_info: FuzzyScoreInfo; - score_info.score = awful_score; - score_info.prev = miss; - matcher.scores[p][w][a] = score_info; - ref := matcher.pattern_role[:matcher.pattern_count]; - matcher.pattern_type_set = fuzzy_calculate_roles(matcher.pattern, &ref); - } + for w := 0; w < p; w += 1 { - } + for a := 0; a < 2; a += 1 { + score_info: FuzzyScoreInfo; + score_info.score = awful_score; + score_info.prev = miss; + matcher.scores[p][w][a] = score_info; + ref := matcher.pattern_role[:matcher.pattern_count]; + matcher.pattern_type_set = fuzzy_calculate_roles(matcher.pattern, &ref); + } + } + } - - } - - return matcher; + return matcher; } -fuzzy_to_acronym :: proc(word: string) -> (string, bool) { +fuzzy_to_acronym :: proc (word: string) -> (string, bool) { - builder := strings.make_builder(context.temp_allocator); + builder := strings.make_builder(context.temp_allocator); - if len(word) <= 1 { - return "", false; - } + if len(word) <= 1 { + return "", false; + } - i := 1; - last_char := word[0]; + i := 1; + last_char := word[0]; - strings.write_byte(&builder, last_char); + strings.write_byte(&builder, last_char); - for i < len(word) { + for i < len(word) { - if last_char == '_' { - strings.write_byte(&builder, word[i]); - } + if last_char == '_' { + strings.write_byte(&builder, word[i]); + } - last_char = word[i]; + last_char = word[i]; - i += 1; - } + i += 1; + } - str := strings.to_string(builder); + str := strings.to_string(builder); - if len(str) <= 1 { - return "", false; - } + if len(str) <= 1 { + return "", false; + } - return str, true; + return str, true; } fuzzy_match :: proc (matcher: ^FuzzyMatcher, word: string) -> (f32, bool) { - if !fuzzy_init(matcher, word) { - return 0, false; - } + if !fuzzy_init(matcher, word) { + return 0, false; + } - if matcher.pattern_count <= 0 { - return 1, true; - } + if matcher.pattern_count <= 0 { + return 1, true; + } - if acronym, ok := fuzzy_to_acronym(word); ok { - if acronym == matcher.pattern { - return 20, true; - } - } + if acronym, ok := fuzzy_to_acronym(word); ok { + if acronym == matcher.pattern { + return 20, true; + } + } - fuzzy_build_graph(matcher); + fuzzy_build_graph(matcher); - best := max(cast(int)matcher.scores[matcher.pattern_count][matcher.word_count][miss].score, - cast(int)matcher.scores[matcher.pattern_count][matcher.word_count][match].score); + best := max(cast(int)matcher.scores[matcher.pattern_count][matcher.word_count][miss].score, + cast(int)matcher.scores[matcher.pattern_count][matcher.word_count][match].score); - if fuzzy_is_awful(best) { - return 0.0, false; - } + if fuzzy_is_awful(best) { + return 0.0, false; + } - score := matcher.score_scale * min(perfect_bonus * cast(f32)matcher.pattern_count, cast(f32)max(0, best)); + score := matcher.score_scale * min(perfect_bonus * cast(f32)matcher.pattern_count, cast(f32)max(0, best)); - if matcher.word_count == matcher.pattern_count { - score *= 2; - } + if matcher.word_count == matcher.pattern_count { + score *= 2; + } - return score, true; + return score, true; } -fuzzy_is_awful :: proc(s: int) -> bool { - return s < awful_score / 2; +fuzzy_is_awful :: proc (s: int) -> bool { + return s < awful_score / 2; } -fuzzy_calculate_roles :: proc(text: string, roles: ^[] FuzzyCharRole) -> FuzzyCharTypeSet { +fuzzy_calculate_roles :: proc (text: string, roles: ^[]FuzzyCharRole) -> FuzzyCharTypeSet { - assert(len(text) == len(roles)); + assert(len(text) == len(roles)); - if len(text) == 0 { - return 0; - } + if len(text) == 0 { + return 0; + } - type: FuzzyCharType = cast(FuzzyCharType)fuzzy_packed_lookup(char_types, cast(uint)text[0]); + type: FuzzyCharType = cast(FuzzyCharType)fuzzy_packed_lookup(char_types, cast(uint)text[0]); - type_set: FuzzyCharTypeSet = cast(u8)(1 << cast(uint)type); + type_set: FuzzyCharTypeSet = cast(u8)(1 << cast(uint)type); - types := type; + types := type; - for i := 0; i < len(text) - 1; i += 1 { - type = cast(FuzzyCharType)fuzzy_packed_lookup(char_types, cast(uint)text[i+1]); - type_set |= 1 << cast(uint)type; + for i := 0; i < len(text) - 1; i += 1 { + type = cast(FuzzyCharType)fuzzy_packed_lookup(char_types, cast(uint)text[i + 1]); + type_set |= 1 << cast(uint)type; - fuzzy_rotate(type, &types); + fuzzy_rotate(type, &types); - roles[i] = cast(FuzzyCharRole)fuzzy_packed_lookup(char_roles, cast(uint)types); - } + roles[i] = cast(FuzzyCharRole)fuzzy_packed_lookup(char_roles, cast(uint)types); + } - fuzzy_rotate(.Empty, &types); + fuzzy_rotate(.Empty, &types); - roles[len(text) - 1] = cast(FuzzyCharRole) fuzzy_packed_lookup(char_roles, cast(uint)types); + roles[len(text) - 1] = cast(FuzzyCharRole)fuzzy_packed_lookup(char_roles, cast(uint)types); - return type_set; + return type_set; } -fuzzy_rotate :: proc(t: FuzzyCharType, types: ^FuzzyCharType) { - types^ = cast(FuzzyCharType)(((cast(uint)types^ << 2) | cast(uint)t) & 0x3f); +fuzzy_rotate :: proc (t: FuzzyCharType, types: ^FuzzyCharType) { + types^ = cast(FuzzyCharType)(((cast(uint)types^ << 2) | cast(uint)t) & 0x3f); } -fuzzy_packed_lookup :: proc(data: $A/[]$T, i: uint) -> T { - return (data[i >> 2] >> ((i & 3) * 2)) & 3; +fuzzy_packed_lookup :: proc (data: $A/[]$T, i: uint) -> T { + return (data[i >> 2] >> ((i & 3) * 2)) & 3; } -fuzzy_init :: proc(matcher: ^FuzzyMatcher, word: string) -> bool { - - matcher.word = word; - matcher.word_count = min(max_word, len(matcher.word)); +fuzzy_init :: proc (matcher: ^FuzzyMatcher, word: string) -> bool { - if matcher.pattern_count > matcher.word_count { - return false; - } + matcher.word = word; + matcher.word_count = min(max_word, len(matcher.word)); - if matcher.pattern_count == 0 { - return true; - } + if matcher.pattern_count > matcher.word_count { + return false; + } - matcher.lower_word = strings.to_lower(word, context.temp_allocator); + if matcher.pattern_count == 0 { + return true; + } - w, p := 0, 0; + matcher.lower_word = strings.to_lower(word, context.temp_allocator); - for ; p != matcher.pattern_count; w += 1{ - if w == matcher.word_count { - return false; - } + w, p := 0, 0; - if matcher.lower_word[w] == matcher.lower_pattern[p] { - p += 1; - } - } + for ; p != matcher.pattern_count; w += 1 { + if w == matcher.word_count { + return false; + } + if matcher.lower_word[w] == matcher.lower_pattern[p] { + p += 1; + } + } - ref := matcher.word_role[:matcher.word_count]; + ref := matcher.word_role[:matcher.word_count]; - matcher.word_type_set = fuzzy_calculate_roles(word, &ref); + matcher.word_type_set = fuzzy_calculate_roles(word, &ref); - return true; + return true; } -fuzzy_skip_penalty :: proc(matcher: ^FuzzyMatcher, w: int) -> int { +fuzzy_skip_penalty :: proc (matcher: ^FuzzyMatcher, w: int) -> int { - if w == 0 { // Skipping the first character. - return 3; - } + if w == 0 { // Skipping the first character. + return 3; + } - if matcher.word_role[w] == .Head { // Skipping a segment. - return 1; - } + if matcher.word_role[w] == .Head { // Skipping a segment. + return 1; + } - return 0; + return 0; } -fuzzy_build_graph :: proc(matcher: ^FuzzyMatcher) { - - for w := 0; w < matcher.word_count; w += 1 { - - s: FuzzyScoreInfo; +fuzzy_build_graph :: proc (matcher: ^FuzzyMatcher) { - score := cast(int)matcher.scores[0][w][miss].score; - penalty := fuzzy_skip_penalty(matcher, w); - sum := score - penalty; + for w := 0; w < matcher.word_count; w += 1 { - s.score = sum; - s.prev = miss; + s: FuzzyScoreInfo; - matcher.scores[0][w + 1][miss] = s; + score := cast(int)matcher.scores[0][w][miss].score; + penalty := fuzzy_skip_penalty(matcher, w); + sum := score - penalty; - s.score = awful_score; - s.prev = miss; + s.score = sum; + s.prev = miss; - matcher.scores[0][w + 1][match] = s; + matcher.scores[0][w + 1][miss] = s; - } + s.score = awful_score; + s.prev = miss; - for p := 0; p < matcher.pattern_count; p += 1 { + matcher.scores[0][w + 1][match] = s; + } - for w := p; w < matcher.word_count; w += 1 { - score := &matcher.scores[p + 1][w + 1]; - pre_miss := &matcher.scores[p + 1][w]; + for p := 0; p < matcher.pattern_count; p += 1 { - match_miss_score := pre_miss[match].score; - miss_miss_score := pre_miss[miss].score; + for w := p; w < matcher.word_count; w += 1 { + score := &matcher.scores[p + 1][w + 1]; + pre_miss := &matcher.scores[p + 1][w]; - if p < matcher.pattern_count - 1 { - match_miss_score -= fuzzy_skip_penalty(matcher, w); - miss_miss_score -= fuzzy_skip_penalty(matcher, w); - } + match_miss_score := pre_miss[match].score; + miss_miss_score := pre_miss[miss].score; - if match_miss_score > miss_miss_score { - s: FuzzyScoreInfo; - s.score = match_miss_score; - s.prev = match; - score[miss] = s; - } + if p < matcher.pattern_count - 1 { + match_miss_score -= fuzzy_skip_penalty(matcher, w); + miss_miss_score -= fuzzy_skip_penalty(matcher, w); + } - else { - s: FuzzyScoreInfo; - s.score = miss_miss_score; - s.prev = miss; - score[miss] = s; - } + if match_miss_score > miss_miss_score { + s: FuzzyScoreInfo; + s.score = match_miss_score; + s.prev = match; + score[miss] = s; + } else { + s: FuzzyScoreInfo; + s.score = miss_miss_score; + s.prev = miss; + score[miss] = s; + } - pre_match := &matcher.scores[p][w]; + pre_match := &matcher.scores[p][w]; - match_match_score := fuzzy_allow_match(matcher, p, w, match) ? - cast(int)pre_match[match].score + fuzzy_match_bonus(matcher, p, w, match) - : awful_score; - - miss_match_score := fuzzy_allow_match(matcher, p, w, miss) ? - cast(int)pre_match[miss].score + fuzzy_match_bonus(matcher, p, w, miss) - : awful_score; - - if match_match_score > miss_match_score { - s: FuzzyScoreInfo; - s.score = match_match_score; - s.prev = match; - score[match] = s; - } - - else { - s: FuzzyScoreInfo; - s.score = miss_match_score; - s.prev = miss; - score[match] = s; - } - - } - - } + match_match_score := fuzzy_allow_match(matcher, p, w, match) ? cast(int)pre_match[match].score + fuzzy_match_bonus(matcher, p, w, match) : awful_score; + miss_match_score := fuzzy_allow_match(matcher, p, w, miss) ? cast(int)pre_match[miss].score + fuzzy_match_bonus(matcher, p, w, miss) : awful_score; + if match_match_score > miss_match_score { + s: FuzzyScoreInfo; + s.score = match_match_score; + s.prev = match; + score[match] = s; + } else { + s: FuzzyScoreInfo; + s.score = miss_match_score; + s.prev = miss; + score[match] = s; + } + } + } } - -fuzzy_match_bonus :: proc(matcher: ^FuzzyMatcher, p: int, w: int, last: int) -> int { - - assert(matcher.lower_pattern[p] == matcher.lower_word[w]); - - s := 1; - - is_pattern_single_case := (cast(uint)matcher.pattern_type_set == 1 << cast(uint)FuzzyCharType.Lower); - is_pattern_single_case |= (cast(uint)matcher.pattern_type_set == 1 << cast(uint)FuzzyCharType.Upper); - - // Bonus: case matches, or a Head in the pattern aligns with one in the word. - // Single-case patterns lack segmentation signals and we assume any character - // can be a head of a segment. - if matcher.pattern[p] == matcher.word[w] || - (matcher.word_role[w] == FuzzyCharRole.Head && - (is_pattern_single_case || matcher.pattern_role[p] == FuzzyCharRole.Head)) { - s += 1; - //fmt.println("match 1"); - } - - // Bonus: a consecutive match. First character match also gets a bonus to - // ensure prefix final match score normalizes to 1.0. - if w == 0 || last == match { - s += 2; - //fmt.println("match 2"); - } - - // Penalty: matching inside a segment (and previous char wasn't matched). - if matcher.word_role[w] == FuzzyCharRole.Tail && p > 0 && last == miss { - s -= 3; - //fmt.println("match 3"); - } - - // Penalty: a Head in the pattern matches in the middle of a word segment. - if matcher.pattern_role[p] == FuzzyCharRole.Head && matcher.word_role[w] == FuzzyCharRole.Tail { - s -= 1; - //fmt.println("match 4"); - } - - // Penalty: matching the first pattern character in the middle of a segment. - if p == 0 && matcher.word_role[w] == FuzzyCharRole.Tail { - s -= 4; - //fmt.println("match 5"); - } - - assert(s <= perfect_bonus); - - return s; +fuzzy_match_bonus :: proc (matcher: ^FuzzyMatcher, p: int, w: int, last: int) -> int { + + assert(matcher.lower_pattern[p] == matcher.lower_word[w]); + + s := 1; + + is_pattern_single_case := (cast(uint)matcher.pattern_type_set == 1 << cast(uint)FuzzyCharType.Lower); + is_pattern_single_case |= (cast(uint)matcher.pattern_type_set == 1 << cast(uint)FuzzyCharType.Upper); + + // Bonus: case matches, or a Head in the pattern aligns with one in the word. + // Single-case patterns lack segmentation signals and we assume any character + // can be a head of a segment. + if matcher.pattern[p] == matcher.word[w] || + (matcher.word_role[w] == FuzzyCharRole.Head && + (is_pattern_single_case || matcher.pattern_role[p] == FuzzyCharRole.Head)) { + s += 1; + //fmt.println("match 1"); + } + + // Bonus: a consecutive match. First character match also gets a bonus to + // ensure prefix final match score normalizes to 1.0. + if w == 0 || last == match { + s += 2; + //fmt.println("match 2"); + } + + // Penalty: matching inside a segment (and previous char wasn't matched). + if matcher.word_role[w] == FuzzyCharRole.Tail && p > 0 && last == miss { + s -= 3; + //fmt.println("match 3"); + } + + // Penalty: a Head in the pattern matches in the middle of a word segment. + if matcher.pattern_role[p] == FuzzyCharRole.Head && matcher.word_role[w] == FuzzyCharRole.Tail { + s -= 1; + //fmt.println("match 4"); + } + + // Penalty: matching the first pattern character in the middle of a segment. + if p == 0 && matcher.word_role[w] == FuzzyCharRole.Tail { + s -= 4; + //fmt.println("match 5"); + } + + assert(s <= perfect_bonus); + + return s; } -fuzzy_allow_match :: proc(matcher: ^FuzzyMatcher, p: int, w: int, last: int) -> bool { - - if matcher.lower_pattern[p] != matcher.lower_word[w] { - return false; - } +fuzzy_allow_match :: proc (matcher: ^FuzzyMatcher, p: int, w: int, last: int) -> bool { - if last == miss { + if matcher.lower_pattern[p] != matcher.lower_word[w] { + return false; + } - if matcher.word_role[w] == FuzzyCharRole.Tail && (matcher.word[w] == matcher.lower_word[w] || - 0 >= (cast(uint)matcher.word_type_set & 1 << cast(uint)FuzzyCharType.Lower)) { - return false; - } + if last == miss { - } - - return true; -} + if matcher.word_role[w] == FuzzyCharRole.Tail && (matcher.word[w] == matcher.lower_word[w] || + 0 >= (cast(uint)matcher.word_type_set & 1 << cast(uint)FuzzyCharType.Lower)) { + return false; + } + } + return true; +}
\ No newline at end of file diff --git a/src/common/pool.odin b/src/common/pool.odin index e82bc38..6789b63 100644 --- a/src/common/pool.odin +++ b/src/common/pool.odin @@ -12,39 +12,36 @@ Task_Status :: enum i32 { Term, } -Task_Proc :: #type proc(task: ^Task); +Task_Proc :: proc (task: ^Task); Task :: struct { - procedure: Task_Proc, - data: rawptr, + procedure: Task_Proc, + data: rawptr, user_index: int, } -Task_Id :: distinct i32; +Task_Id :: distinct i32; INVALID_TASK_ID :: Task_Id(-1); - Pool :: struct { allocator: mem.Allocator, mutex: sync.Mutex, sem_available: sync.Semaphore, processing_task_count: int, // atomic is_running: bool, - - threads: []^thread.Thread, - - tasks: [dynamic]Task, + threads: []^thread.Thread, + tasks: [dynamic]Task, } -pool_init :: proc(pool: ^Pool, thread_count: int, allocator := context.allocator) { - worker_thread_internal :: proc(t: ^thread.Thread) { +pool_init :: proc (pool: ^Pool, thread_count: int, allocator := context.allocator) { + worker_thread_internal :: proc (t: ^thread.Thread) { pool := (^Pool)(t.data); - temp_allocator: Scratch_Allocator; + temp_allocator: Scratch_Allocator; - scratch_allocator_init(&temp_allocator, mem.megabytes(6)); + scratch_allocator_init(&temp_allocator, mem.megabytes(6)); - context.temp_allocator = scratch_allocator(&temp_allocator); + context.temp_allocator = scratch_allocator(&temp_allocator); for pool.is_running { sync.semaphore_wait_for(&pool.sem_available); @@ -53,19 +50,18 @@ pool_init :: proc(pool: ^Pool, thread_count: int, allocator := context.allocator pool_do_work(pool, &task); } - free_all(context.temp_allocator); + free_all(context.temp_allocator); } - scratch_allocator_destroy(&temp_allocator); + scratch_allocator_destroy(&temp_allocator); sync.semaphore_post(&pool.sem_available, 1); - } - + }; context.allocator = allocator; - pool.allocator = allocator; - pool.tasks = make([dynamic]Task); - pool.threads = make([]^thread.Thread, thread_count); + pool.allocator = allocator; + pool.tasks = make([dynamic]Task); + pool.threads = make([]^thread.Thread, thread_count); sync.mutex_init(&pool.mutex); sync.semaphore_init(&pool.sem_available); @@ -73,13 +69,13 @@ pool_init :: proc(pool: ^Pool, thread_count: int, allocator := context.allocator for _, i in pool.threads { t := thread.create(worker_thread_internal); - t.user_index = i; - t.data = pool; + t.user_index = i; + t.data = pool; pool.threads[i] = t; } } -pool_destroy :: proc(pool: ^Pool) { +pool_destroy :: proc (pool: ^Pool) { delete(pool.tasks); for t in &pool.threads { @@ -92,13 +88,13 @@ pool_destroy :: proc(pool: ^Pool) { sync.semaphore_destroy(&pool.sem_available); } -pool_start :: proc(pool: ^Pool) { +pool_start :: proc (pool: ^Pool) { for t in pool.threads { thread.start(t); } } -pool_join :: proc(pool: ^Pool) { +pool_join :: proc (pool: ^Pool) { pool.is_running = false; sync.semaphore_post(&pool.sem_available, len(pool.threads)); @@ -110,24 +106,24 @@ pool_join :: proc(pool: ^Pool) { } } -pool_add_task :: proc(pool: ^Pool, procedure: Task_Proc, data: rawptr, user_index: int = 0) { +pool_add_task :: proc (pool: ^Pool, procedure: Task_Proc, data: rawptr, user_index: int = 0) { sync.mutex_lock(&pool.mutex); defer sync.mutex_unlock(&pool.mutex); task: Task; - task.procedure = procedure; - task.data = data; + task.procedure = procedure; + task.data = data; task.user_index = user_index; append(&pool.tasks, task); sync.semaphore_post(&pool.sem_available, 1); } -pool_try_and_pop_task :: proc(pool: ^Pool) -> (task: Task, got_task: bool = false) { +pool_try_and_pop_task :: proc (pool: ^Pool) -> (task: Task, got_task: bool = false) { if sync.mutex_try_lock(&pool.mutex) { if len(pool.tasks) != 0 { intrinsics.atomic_add(&pool.processing_task_count, 1); - task = pop_front(&pool.tasks); + task = pop_front(&pool.tasks); got_task = true; } sync.mutex_unlock(&pool.mutex); @@ -135,14 +131,12 @@ pool_try_and_pop_task :: proc(pool: ^Pool) -> (task: Task, got_task: bool = fals return; } - -pool_do_work :: proc(pool: ^Pool, task: ^Task) { +pool_do_work :: proc (pool: ^Pool, task: ^Task) { task.procedure(task); intrinsics.atomic_sub(&pool.processing_task_count, 1); } - -pool_wait_and_process :: proc(pool: ^Pool) { +pool_wait_and_process :: proc (pool: ^Pool) { for len(pool.tasks) != 0 || intrinsics.atomic_load(&pool.processing_task_count) != 0 { if task, ok := pool_try_and_pop_task(pool); ok { pool_do_work(pool, &task); @@ -159,4 +153,4 @@ pool_wait_and_process :: proc(pool: ^Pool) { } pool_join(pool); -} +}
\ No newline at end of file diff --git a/src/common/position.odin b/src/common/position.odin index 62a4615..9145091 100644 --- a/src/common/position.odin +++ b/src/common/position.odin @@ -6,306 +6,269 @@ import "core:fmt" import "core:odin/ast" /* - This file handles the conversion between utf-16 and utf-8 offsets in the text document + This file handles the conversion between utf-16 and utf-8 offsets in the text document */ //TODO(Optimize by calculating all the newlines at parse instead of calculating them) Position :: struct { - line: int, + line: int, character: int, -}; +} Range :: struct { start: Position, - end: Position, -}; + end: Position, +} Location :: struct { - uri: string, + uri: string, range: Range, -}; - +} AbsoluteRange :: struct { - start: int, - end: int, -}; + start: int, + end: int, +} AbsolutePosition :: int; -get_absolute_position :: proc(position: Position, document_text: [] u8) -> (AbsolutePosition, bool) { - absolute: AbsolutePosition; +get_absolute_position :: proc (position: Position, document_text: []u8) -> (AbsolutePosition, bool) { + absolute: AbsolutePosition; - if len(document_text) == 0 { - absolute = 0; - return absolute, true; - } + if len(document_text) == 0 { + absolute = 0; + return absolute, true; + } - line_count := 0; - index := 1; - last := document_text[0]; + line_count := 0; + index := 1; + last := document_text[0]; - if !get_index_at_line(&index, &line_count, &last, document_text, position.line) { - return absolute, false; - } + if !get_index_at_line(&index, &line_count, &last, document_text, position.line) { + return absolute, false; + } - absolute = index + get_character_offset_u16_to_u8(position.character, document_text[index:]); + absolute = index + get_character_offset_u16_to_u8(position.character, document_text[index:]); - return absolute, true; + return absolute, true; } -get_relative_token_position :: proc(offset: int, document_text: [] u8, current_start: int) -> Position { - - start_index := current_start; - - data := document_text[start_index:]; - - i: int; +get_relative_token_position :: proc (offset: int, document_text: []u8, current_start: int) -> Position { - position: Position; + start_index := current_start; - for i + start_index < offset { + data := document_text[start_index:]; - r, w := utf8.decode_rune(data[i:]); + i: int; - if r == '\n' { //\r? - position.character = 0; - position.line += 1; - i += 1; - } + position: Position; - else if w == 0 { - return position; - } + for i + start_index < offset { - else { - if r < 0x10000 { - position.character += 1; - } + r, w := utf8.decode_rune(data[i:]); - else { - position.character += 2; - } + if r == '\n' { //\r? + position.character = 0; + position.line += 1; + i += 1; + } else if w == 0 { + return position; + } else { + if r < 0x10000 { + position.character += 1; + } else { + position.character += 2; + } - i += w; - } - } + i += w; + } + } - return position; + return position; } /* - Get the range of a token in utf16 space - */ -get_token_range :: proc(node: ast.Node, document_text: [] u8) -> Range { - range: Range; - + Get the range of a token in utf16 space +*/ +get_token_range :: proc (node: ast.Node, document_text: []u8) -> Range { + range: Range; - go_backwards_to_endline :: proc(offset: int, document_text: [] u8) -> int { + go_backwards_to_endline :: proc (offset: int, document_text: []u8) -> int { - index := offset; + index := offset; - for index > 0 && document_text[index] != '\n' && document_text[index] != '\r' { - index -= 1; - } + for index > 0 && document_text[index] != '\n' && document_text[index] != '\r' { + index -= 1; + } - if index == 0 { - return 0; - } + if index == 0 { + return 0; + } - return index+1; - } + return index + 1; + }; - pos_offset := min(len(document_text)-1, node.pos.offset); - end_offset := min(len(document_text)-1, node.end.offset); + pos_offset := min(len(document_text) - 1, node.pos.offset); + end_offset := min(len(document_text) - 1, node.end.offset); - offset := go_backwards_to_endline(pos_offset, document_text); + offset := go_backwards_to_endline(pos_offset, document_text); - range.start.line = node.pos.line-1; - range.start.character = get_character_offset_u8_to_u16(node.pos.column-1, document_text[offset:]); + range.start.line = node.pos.line - 1; + range.start.character = get_character_offset_u8_to_u16(node.pos.column - 1, document_text[offset:]); - offset = go_backwards_to_endline(end_offset, document_text); + offset = go_backwards_to_endline(end_offset, document_text); - range.end.line = node.end.line-1; - range.end.character = get_character_offset_u8_to_u16(node.end.column-1, document_text[offset:]); + range.end.line = node.end.line - 1; + range.end.character = get_character_offset_u8_to_u16(node.end.column - 1, document_text[offset:]); - return range; + return range; } -get_absolute_range :: proc(range: Range, document_text: [] u8) -> (AbsoluteRange, bool) { +get_absolute_range :: proc (range: Range, document_text: []u8) -> (AbsoluteRange, bool) { - absolute: AbsoluteRange; + absolute: AbsoluteRange; - if len(document_text) == 0 { - absolute.start = 0; - absolute.end = 0; - return absolute, true; - } + if len(document_text) == 0 { + absolute.start = 0; + absolute.end = 0; + return absolute, true; + } - line_count := 0; - index := 1; - last := document_text[0]; + line_count := 0; + index := 1; + last := document_text[0]; - if !get_index_at_line(&index, &line_count, &last, document_text, range.start.line) { - return absolute, false; - } + if !get_index_at_line(&index, &line_count, &last, document_text, range.start.line) { + return absolute, false; + } - absolute.start = index + get_character_offset_u16_to_u8(range.start.character, document_text[index:]); + absolute.start = index + get_character_offset_u16_to_u8(range.start.character, document_text[index:]); - //if the last line was indexed at zero we have to move it back to index 1. - //This happens when line = 0 - if index == 0 { - index = 1; - } + //if the last line was indexed at zero we have to move it back to index 1. + //This happens when line = 0 + if index == 0 { + index = 1; + } - if !get_index_at_line(&index, &line_count, &last, document_text, range.end.line) { - return absolute, false; - } + if !get_index_at_line(&index, &line_count, &last, document_text, range.end.line) { + return absolute, false; + } - absolute.end = index + get_character_offset_u16_to_u8(range.end.character, document_text[index:]); + absolute.end = index + get_character_offset_u16_to_u8(range.end.character, document_text[index:]); - return absolute, true; + return absolute, true; } +get_index_at_line :: proc (current_index: ^int, current_line: ^int, last: ^u8, document_text: []u8, end_line: int) -> bool { -get_index_at_line :: proc(current_index: ^int, current_line: ^int, last: ^u8, document_text: []u8, end_line: int) -> bool { - - if end_line == 0 { - current_index^ = 0; - return true; - } - - if current_line^ == end_line { - return true; - } - - - for ; current_index^ < len(document_text); current_index^ += 1 { - - current := document_text[current_index^]; + if end_line == 0 { + current_index^ = 0; + return true; + } - if last^ == '\r' { - current_line^ += 1; + if current_line^ == end_line { + return true; + } - if current_line^ == end_line { - last^ = current; - current_index^ += 1; - return true; - } + for ; current_index^ < len(document_text); current_index^ += 1 { - } + current := document_text[current_index^]; - else if current == '\n' { - current_line^ += 1; + if last^ == '\r' { + current_line^ += 1; - if current_line^ == end_line { - last^ = current; - current_index^ += 1; - return true; - } + if current_line^ == end_line { + last^ = current; + current_index^ += 1; + return true; + } + } else if current == '\n' { + current_line^ += 1; - } + if current_line^ == end_line { + last^ = current; + current_index^ += 1; + return true; + } + } - last^ = document_text[current_index^]; - } - - return false; + last^ = document_text[current_index^]; + } + return false; } -get_character_offset_u16_to_u8 :: proc(character_offset: int, document_text: [] u8) -> int { - - utf8_idx := 0; - utf16_idx := 0; - - for utf16_idx < character_offset { - - r, w := utf8.decode_rune(document_text[utf8_idx:]); +get_character_offset_u16_to_u8 :: proc (character_offset: int, document_text: []u8) -> int { - if r == '\n' { - return utf8_idx; - } + utf8_idx := 0; + utf16_idx := 0; - else if w == 0 { - return utf8_idx; - } + for utf16_idx < character_offset { - else if r < 0x10000 { - utf16_idx += 1; - } + r, w := utf8.decode_rune(document_text[utf8_idx:]); - else { - utf16_idx += 2; - } + if r == '\n' { + return utf8_idx; + } else if w == 0 { + return utf8_idx; + } else if r < 0x10000 { + utf16_idx += 1; + } else { + utf16_idx += 2; + } - utf8_idx += w; + utf8_idx += w; + } - } - - return utf8_idx; + return utf8_idx; } -get_character_offset_u8_to_u16 :: proc(character_offset: int, document_text: [] u8) -> int { - - utf8_idx := 0; - utf16_idx := 0; - - for utf8_idx < character_offset { +get_character_offset_u8_to_u16 :: proc (character_offset: int, document_text: []u8) -> int { - r, w := utf8.decode_rune(document_text[utf8_idx:]); + utf8_idx := 0; + utf16_idx := 0; - if r == '\n' { - return utf16_idx; - } + for utf8_idx < character_offset { - else if w == 0 { - return utf16_idx; - } + r, w := utf8.decode_rune(document_text[utf8_idx:]); - else if r < 0x10000 { - utf16_idx += 1; - } + if r == '\n' { + return utf16_idx; + } else if w == 0 { + return utf16_idx; + } else if r < 0x10000 { + utf16_idx += 1; + } else { + utf16_idx += 2; + } - else { - utf16_idx += 2; - } - - utf8_idx += w; - - } - - return utf16_idx; + utf8_idx += w; + } + return utf16_idx; } -get_end_line_u16 :: proc(document_text: [] u8) -> int { - - utf8_idx := 0; - utf16_idx := 0; - - for utf8_idx < len(document_text) { - r, w := utf8.decode_rune(document_text[utf8_idx:]); - - if r == '\n' { - return utf16_idx; - } - - else if w == 0 { - return utf16_idx; - } +get_end_line_u16 :: proc (document_text: []u8) -> int { - else if r < 0x10000 { - utf16_idx += 1; - } + utf8_idx := 0; + utf16_idx := 0; - else { - utf16_idx += 2; - } + for utf8_idx < len(document_text) { + r, w := utf8.decode_rune(document_text[utf8_idx:]); - utf8_idx += w; + if r == '\n' { + return utf16_idx; + } else if w == 0 { + return utf16_idx; + } else if r < 0x10000 { + utf16_idx += 1; + } else { + utf16_idx += 2; + } - } + utf8_idx += w; + } - return utf16_idx; + return utf16_idx; }
\ No newline at end of file diff --git a/src/common/pretty.odin b/src/common/pretty.odin index 2255621..ff0d5ff 100644 --- a/src/common/pretty.odin +++ b/src/common/pretty.odin @@ -3,244 +3,238 @@ package common import "core:odin/ast" import "core:fmt" - /* - Ast visualization to help in debugging and development - */ - -print_ast :: proc{ - print_ast_array, - print_ast_dynamic_array, - print_ast_node, -}; + Ast visualization to help in debugging and development +*/ -print_ast_array :: proc(array: $A/[]^$T, depth: int, src: []byte, newline := false) { +print_ast :: proc { +print_ast_array, +print_ast_dynamic_array, +print_ast_node}; - for elem, i in array { - print_ast(elem, depth, src); - } +print_ast_array :: proc (array: $A/[]^$T, depth: int, src: []byte, newline := false) { + for elem, i in array { + print_ast(elem, depth, src); + } } -print_ast_dynamic_array :: proc(array: $A/[dynamic]^$T, depth: int, src: []byte, newline := false) { - - for elem, i in array { - print_ast(elem, depth, src); - } +print_ast_dynamic_array :: proc (array: $A/[dynamic]^$T, depth: int, src: []byte, newline := false) { + for elem, i in array { + print_ast(elem, depth, src); + } } /* - Not fully printed out, filling it in as needed. - */ - -print_ast_node :: proc(node: ^ast.Node, depth: int, src: []byte, newline := false) { - - using ast; - - if node == nil { - return; - } - - if newline { - fmt.println(); - - for i := 0; i < depth; i += 1 { - fmt.printf(" ", ); - } - - } - - name := string(src[node.pos.offset:node.end.offset]); - - switch n in node.derived { - case Bad_Expr: - case Ident: - fmt.printf(" %v ", n.name); - case Implicit: - case Undef: - case Basic_Lit: - case Ellipsis: - print_ast(n.expr, depth + 1, src); - case Proc_Lit: - fmt.printf("function"); - print_ast(n.type, depth + 1, src); - print_ast(n.body, depth + 1, src, true); - case Comp_Lit: - print_ast(n.type, depth + 1, src); - print_ast(n.elems, depth + 1, src); - case Tag_Expr: - print_ast(n.expr, depth + 1, src); - case Unary_Expr: - print_ast(n.expr, depth + 1, src); - case Binary_Expr: - print_ast(n.left, depth + 1, src); - fmt.printf("%v", n.op.text); - print_ast(n.right, depth + 1, src); - case Paren_Expr: - print_ast(n.expr, depth + 1, src); - case Call_Expr: - fmt.printf("call"); - print_ast(n.expr, depth + 1, src); - fmt.printf("("); - print_ast(n.args, depth + 1, src); - fmt.printf(")"); - case Selector_Expr: - print_ast(n.expr, depth + 1, src); - fmt.printf("."); - print_ast(n.field, depth + 1, src); - case Index_Expr: - print_ast(n.expr, depth + 1, src); - print_ast(n.index, depth + 1, src); - case Deref_Expr: - print_ast(n.expr, depth + 1, src); - case Slice_Expr: - print_ast(n.expr, depth + 1, src); - print_ast(n.low, depth + 1, src); - print_ast(n.high, depth + 1, src); - case Field_Value: - print_ast(n.field, depth + 1, src); - print_ast(n.value, depth + 1, src); - case Ternary_Expr: - print_ast(n.cond, depth + 1, src); - print_ast(n.x, depth + 1, src); - print_ast(n.y, depth + 1, src); - case Ternary_If_Expr: - print_ast(n.x, depth + 1, src); - print_ast(n.cond, depth + 1, src); - print_ast(n.y, depth + 1, src); - case Ternary_When_Expr: - print_ast(n.x, depth + 1, src); - print_ast(n.cond, depth + 1, src); - print_ast(n.y, depth + 1, src); - case Type_Assertion: - print_ast(n.expr, depth + 1, src); - print_ast(n.type, depth + 1, src); - case Type_Cast: - print_ast(n.type, depth + 1, src); - print_ast(n.expr, depth + 1, src); - case Auto_Cast: - print_ast(n.expr, depth + 1, src); - case Bad_Stmt: - case Empty_Stmt: - case Expr_Stmt: - print_ast(n.expr, depth + 1, src); - case Tag_Stmt: - r := cast(^Expr_Stmt)node; - print_ast(r.expr, depth + 1, src); - case Assign_Stmt: - print_ast(n.lhs, depth + 1, src); - print_ast(n.rhs, depth + 1, src); - case Block_Stmt: - print_ast(n.label, depth + 1, src); - print_ast(n.stmts, depth + 1, src); - case If_Stmt: - print_ast(n.label, depth + 1, src); - print_ast(n.init, depth + 1, src); - print_ast(n.cond, depth + 1, src); - print_ast(n.body, depth + 1, src); - print_ast(n.else_stmt, depth + 1, src); - case When_Stmt: - print_ast(n.cond, depth + 1, src); - print_ast(n.body, depth + 1, src); - print_ast(n.else_stmt, depth + 1, src); - case Return_Stmt: - print_ast(n.results, depth + 1, src); - case Defer_Stmt: - print_ast(n.stmt, depth + 1, src); - case For_Stmt: - print_ast(n.label, depth + 1, src); - print_ast(n.init, depth + 1, src); - print_ast(n.cond, depth + 1, src); - print_ast(n.post, depth + 1, src); - print_ast(n.body, depth + 1, src); - case Range_Stmt: - print_ast(n.label, depth + 1, src); - print_ast(n.val0, depth + 1, src); - print_ast(n.val1, depth + 1, src); - print_ast(n.expr, depth + 1, src); - print_ast(n.body, depth + 1, src); - case Case_Clause: - print_ast(n.list, depth + 1, src); - print_ast(n.body, depth + 1, src); - case Switch_Stmt: - print_ast(n.label, depth + 1, src); - print_ast(n.init, depth + 1, src); - print_ast(n.cond, depth + 1, src); - print_ast(n.body, depth + 1, src); - case Type_Switch_Stmt: - print_ast(n.label, depth + 1, src); - print_ast(n.tag, depth + 1, src); - print_ast(n.expr, depth + 1, src); - print_ast(n.body, depth + 1, src); - case Branch_Stmt: - print_ast(n.label, depth + 1, src); - case Using_Stmt: - print_ast(n.list, depth + 1, src); - case Bad_Decl: - case Value_Decl: - print_ast(n.attributes, depth + 1, src); - print_ast(n.names, depth + 1, src); - print_ast(n.type, depth + 1, src); - print_ast(n.values, depth + 1, src); - fmt.println(); - case Package_Decl: - case Import_Decl: - case Foreign_Block_Decl: - print_ast(n.attributes, depth + 1, src); - print_ast(n.foreign_library, depth + 1, src); - print_ast(n.body, depth + 1, src); - case Foreign_Import_Decl: - print_ast(n.name, depth + 1, src); - case Proc_Group: - print_ast(n.args, depth + 1, src); - case Attribute: - print_ast(n.elems, depth + 1, src); - case Field: - print_ast(n.names, depth + 1, src); - print_ast(n.type, depth + 1, src); - print_ast(n.default_value, depth + 1, src); - case Field_List: - print_ast(n.list, depth + 1, src); - case Typeid_Type: - print_ast(n.specialization, depth + 1, src); - case Helper_Type: - print_ast(n.type, depth + 1, src); - case Distinct_Type: - print_ast(n.type, depth + 1, src); - case Poly_Type: - print_ast(n.type, depth + 1, src); - print_ast(n.specialization, depth + 1, src); - case Proc_Type: - print_ast(n.params, depth + 1, src); - print_ast(n.results, depth + 1, src); - case Pointer_Type: - print_ast(n.elem, depth + 1, src); - case Array_Type: - print_ast(n.len, depth + 1, src); - print_ast(n.elem, depth + 1, src); - case Dynamic_Array_Type: - print_ast(n.elem, depth + 1, src); - case Struct_Type: - fmt.printf("struct"); - print_ast(n.poly_params, depth + 1, src); - print_ast(n.align, depth + 1, src); - print_ast(n.fields, depth + 1, src); - case Union_Type: - print_ast(n.poly_params, depth + 1, src); - print_ast(n.align, depth + 1, src); - print_ast(n.variants, depth + 1, src); - case Enum_Type: - print_ast(n.base_type, depth + 1, src); - print_ast(n.fields, depth + 1, src); - case Bit_Set_Type: - print_ast(n.elem, depth + 1, src); - print_ast(n.underlying, depth + 1, src); - case Map_Type: - print_ast(n.key, depth + 1, src); - print_ast(n.value, depth + 1, src); - case: - fmt.panicf("Unhandled node kind: %T", n); - } - + Not fully printed out, filling it in as needed. +*/ + +print_ast_node :: proc (node: ^ast.Node, depth: int, src: []byte, newline := false) { + + using ast; + + if node == nil { + return; + } + + if newline { + fmt.println(); + + for i := 0; i < depth; i += 1 { + fmt.printf(" "); + } + } + + name := string(src[node.pos.offset:node.end.offset]); + + switch n in node.derived { + case Bad_Expr: + case Ident: + fmt.printf(" %v ", n.name); + case Implicit: + case Undef: + case Basic_Lit: + case Ellipsis: + print_ast(n.expr, depth + 1, src); + case Proc_Lit: + fmt.printf("function"); + print_ast(n.type, depth + 1, src); + print_ast(n.body, depth + 1, src, true); + case Comp_Lit: + print_ast(n.type, depth + 1, src); + print_ast(n.elems, depth + 1, src); + case Tag_Expr: + print_ast(n.expr, depth + 1, src); + case Unary_Expr: + print_ast(n.expr, depth + 1, src); + case Binary_Expr: + print_ast(n.left, depth + 1, src); + fmt.printf("%v", n.op.text); + print_ast(n.right, depth + 1, src); + case Paren_Expr: + print_ast(n.expr, depth + 1, src); + case Call_Expr: + fmt.printf("call"); + print_ast(n.expr, depth + 1, src); + fmt.printf("("); + print_ast(n.args, depth + 1, src); + fmt.printf(")"); + case Selector_Expr: + print_ast(n.expr, depth + 1, src); + fmt.printf("."); + print_ast(n.field, depth + 1, src); + case Index_Expr: + print_ast(n.expr, depth + 1, src); + print_ast(n.index, depth + 1, src); + case Deref_Expr: + print_ast(n.expr, depth + 1, src); + case Slice_Expr: + print_ast(n.expr, depth + 1, src); + print_ast(n.low, depth + 1, src); + print_ast(n.high, depth + 1, src); + case Field_Value: + print_ast(n.field, depth + 1, src); + print_ast(n.value, depth + 1, src); + case Ternary_Expr: + print_ast(n.cond, depth + 1, src); + print_ast(n.x, depth + 1, src); + print_ast(n.y, depth + 1, src); + case Ternary_If_Expr: + print_ast(n.x, depth + 1, src); + print_ast(n.cond, depth + 1, src); + print_ast(n.y, depth + 1, src); + case Ternary_When_Expr: + print_ast(n.x, depth + 1, src); + print_ast(n.cond, depth + 1, src); + print_ast(n.y, depth + 1, src); + case Type_Assertion: + print_ast(n.expr, depth + 1, src); + print_ast(n.type, depth + 1, src); + case Type_Cast: + print_ast(n.type, depth + 1, src); + print_ast(n.expr, depth + 1, src); + case Auto_Cast: + print_ast(n.expr, depth + 1, src); + case Bad_Stmt: + case Empty_Stmt: + case Expr_Stmt: + print_ast(n.expr, depth + 1, src); + case Tag_Stmt: + r := cast(^Expr_Stmt)node; + print_ast(r.expr, depth + 1, src); + case Assign_Stmt: + print_ast(n.lhs, depth + 1, src); + print_ast(n.rhs, depth + 1, src); + case Block_Stmt: + print_ast(n.label, depth + 1, src); + print_ast(n.stmts, depth + 1, src); + case If_Stmt: + print_ast(n.label, depth + 1, src); + print_ast(n.init, depth + 1, src); + print_ast(n.cond, depth + 1, src); + print_ast(n.body, depth + 1, src); + print_ast(n.else_stmt, depth + 1, src); + case When_Stmt: + print_ast(n.cond, depth + 1, src); + print_ast(n.body, depth + 1, src); + print_ast(n.else_stmt, depth + 1, src); + case Return_Stmt: + print_ast(n.results, depth + 1, src); + case Defer_Stmt: + print_ast(n.stmt, depth + 1, src); + case For_Stmt: + print_ast(n.label, depth + 1, src); + print_ast(n.init, depth + 1, src); + print_ast(n.cond, depth + 1, src); + print_ast(n.post, depth + 1, src); + print_ast(n.body, depth + 1, src); + case Range_Stmt: + print_ast(n.label, depth + 1, src); + print_ast(n.val0, depth + 1, src); + print_ast(n.val1, depth + 1, src); + print_ast(n.expr, depth + 1, src); + print_ast(n.body, depth + 1, src); + case Case_Clause: + print_ast(n.list, depth + 1, src); + print_ast(n.body, depth + 1, src); + case Switch_Stmt: + print_ast(n.label, depth + 1, src); + print_ast(n.init, depth + 1, src); + print_ast(n.cond, depth + 1, src); + print_ast(n.body, depth + 1, src); + case Type_Switch_Stmt: + print_ast(n.label, depth + 1, src); + print_ast(n.tag, depth + 1, src); + print_ast(n.expr, depth + 1, src); + print_ast(n.body, depth + 1, src); + case Branch_Stmt: + print_ast(n.label, depth + 1, src); + case Using_Stmt: + print_ast(n.list, depth + 1, src); + case Bad_Decl: + case Value_Decl: + print_ast(n.attributes, depth + 1, src); + print_ast(n.names, depth + 1, src); + print_ast(n.type, depth + 1, src); + print_ast(n.values, depth + 1, src); + fmt.println(); + case Package_Decl: + case Import_Decl: + case Foreign_Block_Decl: + print_ast(n.attributes, depth + 1, src); + print_ast(n.foreign_library, depth + 1, src); + print_ast(n.body, depth + 1, src); + case Foreign_Import_Decl: + print_ast(n.name, depth + 1, src); + case Proc_Group: + print_ast(n.args, depth + 1, src); + case Attribute: + print_ast(n.elems, depth + 1, src); + case Field: + print_ast(n.names, depth + 1, src); + print_ast(n.type, depth + 1, src); + print_ast(n.default_value, depth + 1, src); + case Field_List: + print_ast(n.list, depth + 1, src); + case Typeid_Type: + print_ast(n.specialization, depth + 1, src); + case Helper_Type: + print_ast(n.type, depth + 1, src); + case Distinct_Type: + print_ast(n.type, depth + 1, src); + case Poly_Type: + print_ast(n.type, depth + 1, src); + print_ast(n.specialization, depth + 1, src); + case Proc_Type: + print_ast(n.params, depth + 1, src); + print_ast(n.results, depth + 1, src); + case Pointer_Type: + print_ast(n.elem, depth + 1, src); + case Array_Type: + print_ast(n.len, depth + 1, src); + print_ast(n.elem, depth + 1, src); + case Dynamic_Array_Type: + print_ast(n.elem, depth + 1, src); + case Struct_Type: + fmt.printf("struct"); + print_ast(n.poly_params, depth + 1, src); + print_ast(n.align, depth + 1, src); + print_ast(n.fields, depth + 1, src); + case Union_Type: + print_ast(n.poly_params, depth + 1, src); + print_ast(n.align, depth + 1, src); + print_ast(n.variants, depth + 1, src); + case Enum_Type: + print_ast(n.base_type, depth + 1, src); + print_ast(n.fields, depth + 1, src); + case Bit_Set_Type: + print_ast(n.elem, depth + 1, src); + print_ast(n.underlying, depth + 1, src); + case Map_Type: + print_ast(n.key, depth + 1, src); + print_ast(n.value, depth + 1, src); + case: + fmt.panicf("Unhandled node kind: %T", n); + } }
\ No newline at end of file diff --git a/src/common/sha1.odin b/src/common/sha1.odin index d3d2119..80a8765 100644 --- a/src/common/sha1.odin +++ b/src/common/sha1.odin @@ -4,47 +4,47 @@ import "core:fmt" //ported version of https://llvm.org/doxygen/SHa1_8cpp_source.html -rol :: proc(number: u32, bits: u32) -> u32 { - return number << bits | number >> (32 - bits); +rol :: proc (number: u32, bits: u32) -> u32 { + return number << bits | number >> (32 - bits); } -blk0 :: proc(buf: [] u32, i: int) -> u32 { - return buf[i]; +blk0 :: proc (buf: []u32, i: int) -> u32 { + return buf[i]; } -blk :: proc(buf: [] u32, i: int) -> u32 { - buf[i & 15] = rol(buf[(i + 13) & 15] ~ buf[(i + 8) & 15] ~ buf[(i + 2) & 15] - ~ buf[i & 15], 1); +blk :: proc (buf: []u32, i: int) -> u32 { + buf[i & 15] = rol(buf[(i + 13) & 15] ~ buf[(i + 8) & 15] ~ buf[(i + 2) & 15] ~ + buf[i & 15], 1); - return buf[i & 15]; + return buf[i & 15]; } -r0 :: proc(a: ^u32, b: ^u32, c: ^u32, d: ^u32, e: ^u32, i: int, buf: [] u32) { - e^ += ((b^ & (c^ ~ d^)) ~ d^) + blk0(buf, i) + 0x5a827999 + rol(a^, 5); - b^ = rol(b^, 30); +r0 :: proc (a: ^u32, b: ^u32, c: ^u32, d: ^u32, e: ^u32, i: int, buf: []u32) { + e^ += ((b^ & (c^ ~ d^)) ~ d^) + blk0(buf, i) + 0x5a827999 + rol(a^, 5); + b^ = rol(b^, 30); } -r1 :: proc(a: ^u32, b: ^u32, c: ^u32, d: ^u32, e: ^u32, i: int, buf: [] u32) { - e^ += ((b^ & (c^ ~ d^)) ~ d^) + blk(buf, i) + 0x5a827999 + rol(a^, 5); - b^ += rol(b^, 30); +r1 :: proc (a: ^u32, b: ^u32, c: ^u32, d: ^u32, e: ^u32, i: int, buf: []u32) { + e^ += ((b^ & (c^ ~ d^)) ~ d^) + blk(buf, i) + 0x5a827999 + rol(a^, 5); + b^ += rol(b^, 30); } -r2 :: proc(a: ^u32, b: ^u32, c: ^u32, d: ^u32, e: ^u32, i: int, buf: [] u32) { - e^ += (b^ ~ c^ ~ d^) + blk(buf, i) + 0x6ed9eba1 + rol(a^, 5); - b^ += rol(b^, 30); +r2 :: proc (a: ^u32, b: ^u32, c: ^u32, d: ^u32, e: ^u32, i: int, buf: []u32) { + e^ += (b^ ~ c^ ~ d^) + blk(buf, i) + 0x6ed9eba1 + rol(a^, 5); + b^ += rol(b^, 30); } -r3 :: proc(a: ^u32, b: ^u32, c: ^u32, d: ^u32, e: ^u32, i: int, buf: [] u32) { - e^ += (((b^ | c^) & d^) | (b^ & c^)) + blk(buf, i) + 0x8F1bbcdc + rol(a^, 5); - b^ += rol(b^, 30); +r3 :: proc (a: ^u32, b: ^u32, c: ^u32, d: ^u32, e: ^u32, i: int, buf: []u32) { + e^ += (((b^ | c^) & d^) | (b^ & c^)) + blk(buf, i) + 0x8F1bbcdc + rol(a^, 5); + b^ += rol(b^, 30); } -r4 :: proc(a: ^u32, b: ^u32, c: ^u32, d: ^u32, e: ^u32, i: int, buf: [] u32) { - e^ += (b^ ~ c^ ~ d^) + blk(buf, i) + 0xca62c1d6 + rol(a^, 5); - b^ += rol(b^, 30); +r4 :: proc (a: ^u32, b: ^u32, c: ^u32, d: ^u32, e: ^u32, i: int, buf: []u32) { + e^ += (b^ ~ c^ ~ d^) + blk(buf, i) + 0xca62c1d6 + rol(a^, 5); + b^ += rol(b^, 30); } -SHA1_K0 :: 0x5a827999; +SHA1_K0 :: 0x5a827999; SHA1_K20 :: 0x6ed9eba1; SHA1_K40 :: 0x8f1bbcdc; SHA1_K60 :: 0xca62c1d6; @@ -56,254 +56,242 @@ SEED_3 :: 0x10325476; SEED_4 :: 0xc3d2e1f0; BLOCK_LENGTH :: 64; -HASH_LENGTH :: 20; +HASH_LENGTH :: 20; Sha1context :: struct { - buf: struct #raw_union { - c: [BLOCK_LENGTH] byte, - l: [BLOCK_LENGTH/4] u32, - }, - state: [HASH_LENGTH / 4] u32, - byte_count: u32, - buf_offset: u8, -}; - -sha1_init :: proc(state_context: ^Sha1context) { - state_context.state[0] = SEED_0; - state_context.state[1] = SEED_1; - state_context.state[2] = SEED_2; - state_context.state[3] = SEED_3; - state_context.state[4] = SEED_4; - state_context.byte_count = 0; - state_context.buf_offset = 0; + buf: struct #raw_union { + c: [BLOCK_LENGTH]byte, + l: [BLOCK_LENGTH / 4]u32, + }, + state: [HASH_LENGTH / 4]u32, + byte_count: u32, + buf_offset: u8, } -sha1_hash_block :: proc(state_context: ^Sha1context) { - a := state_context.state[0]; - b := state_context.state[1]; - c := state_context.state[2]; - d := state_context.state[3]; - e := state_context.state[4]; - - // 4 rounds of 20 operations each. loop unrolled. - r0(&a, &b, &c, &d, &e, 0, state_context.buf.l[:]); - r0(&e, &a, &b, &c, &d, 1, state_context.buf.l[:]); - r0(&d, &e, &a, &b, &c, 2, state_context.buf.l[:]); - r0(&c, &d, &e, &a, &b, 3, state_context.buf.l[:]); - r0(&b, &c, &d, &e, &a, 4, state_context.buf.l[:]); - r0(&a, &b, &c, &d, &e, 5, state_context.buf.l[:]); - r0(&e, &a, &b, &c, &d, 6, state_context.buf.l[:]); - r0(&d, &e, &a, &b, &c, 7, state_context.buf.l[:]); - r0(&c, &d, &e, &a, &b, 8, state_context.buf.l[:]); - r0(&b, &c, &d, &e, &a, 9, state_context.buf.l[:]); - r0(&a, &b, &c, &d, &e, 10, state_context.buf.l[:]); - r0(&e, &a, &b, &c, &d, 11, state_context.buf.l[:]); - r0(&d, &e, &a, &b, &c, 12, state_context.buf.l[:]); - r0(&c, &d, &e, &a, &b, 13, state_context.buf.l[:]); - r0(&b, &c, &d, &e, &a, 14, state_context.buf.l[:]); - r0(&a, &b, &c, &d, &e, 15, state_context.buf.l[:]); - r1(&e, &a, &b, &c, &d, 16, state_context.buf.l[:]); - r1(&d, &e, &a, &b, &c, 17, state_context.buf.l[:]); - r1(&c, &d, &e, &a, &b, 18, state_context.buf.l[:]); - r1(&b, &c, &d, &e, &a, 19, state_context.buf.l[:]); - - r2(&a, &b, &c, &d, &e, 20, state_context.buf.l[:]); - r2(&e, &a, &b, &c, &d, 21, state_context.buf.l[:]); - r2(&d, &e, &a, &b, &c, 22, state_context.buf.l[:]); - r2(&c, &d, &e, &a, &b, 23, state_context.buf.l[:]); - r2(&b, &c, &d, &e, &a, 24, state_context.buf.l[:]); - r2(&a, &b, &c, &d, &e, 25, state_context.buf.l[:]); - r2(&e, &a, &b, &c, &d, 26, state_context.buf.l[:]); - r2(&d, &e, &a, &b, &c, 27, state_context.buf.l[:]); - r2(&c, &d, &e, &a, &b, 28, state_context.buf.l[:]); - r2(&b, &c, &d, &e, &a, 29, state_context.buf.l[:]); - r2(&a, &b, &c, &d, &e, 30, state_context.buf.l[:]); - r2(&e, &a, &b, &c, &d, 31, state_context.buf.l[:]); - r2(&d, &e, &a, &b, &c, 32, state_context.buf.l[:]); - r2(&c, &d, &e, &a, &b, 33, state_context.buf.l[:]); - r2(&b, &c, &d, &e, &a, 34, state_context.buf.l[:]); - r2(&a, &b, &c, &d, &e, 35, state_context.buf.l[:]); - r2(&e, &a, &b, &c, &d, 36, state_context.buf.l[:]); - r2(&d, &e, &a, &b, &c, 37, state_context.buf.l[:]); - r2(&c, &d, &e, &a, &b, 38, state_context.buf.l[:]); - r2(&b, &c, &d, &e, &a, 39, state_context.buf.l[:]); - - r3(&a, &b, &c, &d, &e, 40, state_context.buf.l[:]); - r3(&e, &a, &b, &c, &d, 41, state_context.buf.l[:]); - r3(&d, &e, &a, &b, &c, 42, state_context.buf.l[:]); - r3(&c, &d, &e, &a, &b, 43, state_context.buf.l[:]); - r3(&b, &c, &d, &e, &a, 44, state_context.buf.l[:]); - r3(&a, &b, &c, &d, &e, 45, state_context.buf.l[:]); - r3(&e, &a, &b, &c, &d, 46, state_context.buf.l[:]); - r3(&d, &e, &a, &b, &c, 47, state_context.buf.l[:]); - r3(&c, &d, &e, &a, &b, 48, state_context.buf.l[:]); - r3(&b, &c, &d, &e, &a, 49, state_context.buf.l[:]); - r3(&a, &b, &c, &d, &e, 50, state_context.buf.l[:]); - r3(&e, &a, &b, &c, &d, 51, state_context.buf.l[:]); - r3(&d, &e, &a, &b, &c, 52, state_context.buf.l[:]); - r3(&c, &d, &e, &a, &b, 53, state_context.buf.l[:]); - r3(&b, &c, &d, &e, &a, 54, state_context.buf.l[:]); - r3(&a, &b, &c, &d, &e, 55, state_context.buf.l[:]); - r3(&e, &a, &b, &c, &d, 56, state_context.buf.l[:]); - r3(&d, &e, &a, &b, &c, 57, state_context.buf.l[:]); - r3(&c, &d, &e, &a, &b, 58, state_context.buf.l[:]); - r3(&b, &c, &d, &e, &a, 59, state_context.buf.l[:]); - - r4(&a, &b, &c, &d, &e, 60, state_context.buf.l[:]); - r4(&e, &a, &b, &c, &d, 61, state_context.buf.l[:]); - r4(&d, &e, &a, &b, &c, 62, state_context.buf.l[:]); - r4(&c, &d, &e, &a, &b, 63, state_context.buf.l[:]); - r4(&b, &c, &d, &e, &a, 64, state_context.buf.l[:]); - r4(&a, &b, &c, &d, &e, 65, state_context.buf.l[:]); - r4(&e, &a, &b, &c, &d, 66, state_context.buf.l[:]); - r4(&d, &e, &a, &b, &c, 67, state_context.buf.l[:]); - r4(&c, &d, &e, &a, &b, 68, state_context.buf.l[:]); - r4(&b, &c, &d, &e, &a, 69, state_context.buf.l[:]); - r4(&a, &b, &c, &d, &e, 70, state_context.buf.l[:]); - r4(&e, &a, &b, &c, &d, 71, state_context.buf.l[:]); - r4(&d, &e, &a, &b, &c, 72, state_context.buf.l[:]); - r4(&c, &d, &e, &a, &b, 73, state_context.buf.l[:]); - r4(&b, &c, &d, &e, &a, 74, state_context.buf.l[:]); - r4(&a, &b, &c, &d, &e, 75, state_context.buf.l[:]); - r4(&e, &a, &b, &c, &d, 76, state_context.buf.l[:]); - r4(&d, &e, &a, &b, &c, 77, state_context.buf.l[:]); - r4(&c, &d, &e, &a, &b, 78, state_context.buf.l[:]); - r4(&b, &c, &d, &e, &a, 79, state_context.buf.l[:]); - - state_context.state[0] += a; - state_context.state[1] += b; - state_context.state[2] += c; - state_context.state[3] += d; - state_context.state[4] += e; - } - - -sha1_add_uncounted :: proc(state_context: ^Sha1context, data: byte) { - - - when ODIN_ENDIAN == "big" { - state_context.buf.c[state_context.buf_offset] = data; - } - - else { - state_context.buf.c[state_context.buf_offset ~ 3] = data; - } - - state_context.buf_offset += 1; - - if state_context.buf_offset == BLOCK_LENGTH { - sha1_hash_block(state_context); - state_context.buf_offset = 0; - } - +sha1_init :: proc (state_context: ^Sha1context) { + state_context.state[0] = SEED_0; + state_context.state[1] = SEED_1; + state_context.state[2] = SEED_2; + state_context.state[3] = SEED_3; + state_context.state[4] = SEED_4; + state_context.byte_count = 0; + state_context.buf_offset = 0; } -sha1_write_byte :: proc(state_context: ^Sha1context, data: byte) { - state_context.byte_count += 1; - sha1_add_uncounted(state_context, data); +sha1_hash_block :: proc (state_context: ^Sha1context) { + a := state_context.state[0]; + b := state_context.state[1]; + c := state_context.state[2]; + d := state_context.state[3]; + e := state_context.state[4]; + + // 4 rounds of 20 operations each. loop unrolled. + r0(&a, &b, &c, &d, &e, 0, state_context.buf.l[:]); + r0(&e, &a, &b, &c, &d, 1, state_context.buf.l[:]); + r0(&d, &e, &a, &b, &c, 2, state_context.buf.l[:]); + r0(&c, &d, &e, &a, &b, 3, state_context.buf.l[:]); + r0(&b, &c, &d, &e, &a, 4, state_context.buf.l[:]); + r0(&a, &b, &c, &d, &e, 5, state_context.buf.l[:]); + r0(&e, &a, &b, &c, &d, 6, state_context.buf.l[:]); + r0(&d, &e, &a, &b, &c, 7, state_context.buf.l[:]); + r0(&c, &d, &e, &a, &b, 8, state_context.buf.l[:]); + r0(&b, &c, &d, &e, &a, 9, state_context.buf.l[:]); + r0(&a, &b, &c, &d, &e, 10, state_context.buf.l[:]); + r0(&e, &a, &b, &c, &d, 11, state_context.buf.l[:]); + r0(&d, &e, &a, &b, &c, 12, state_context.buf.l[:]); + r0(&c, &d, &e, &a, &b, 13, state_context.buf.l[:]); + r0(&b, &c, &d, &e, &a, 14, state_context.buf.l[:]); + r0(&a, &b, &c, &d, &e, 15, state_context.buf.l[:]); + r1(&e, &a, &b, &c, &d, 16, state_context.buf.l[:]); + r1(&d, &e, &a, &b, &c, 17, state_context.buf.l[:]); + r1(&c, &d, &e, &a, &b, 18, state_context.buf.l[:]); + r1(&b, &c, &d, &e, &a, 19, state_context.buf.l[:]); + + r2(&a, &b, &c, &d, &e, 20, state_context.buf.l[:]); + r2(&e, &a, &b, &c, &d, 21, state_context.buf.l[:]); + r2(&d, &e, &a, &b, &c, 22, state_context.buf.l[:]); + r2(&c, &d, &e, &a, &b, 23, state_context.buf.l[:]); + r2(&b, &c, &d, &e, &a, 24, state_context.buf.l[:]); + r2(&a, &b, &c, &d, &e, 25, state_context.buf.l[:]); + r2(&e, &a, &b, &c, &d, 26, state_context.buf.l[:]); + r2(&d, &e, &a, &b, &c, 27, state_context.buf.l[:]); + r2(&c, &d, &e, &a, &b, 28, state_context.buf.l[:]); + r2(&b, &c, &d, &e, &a, 29, state_context.buf.l[:]); + r2(&a, &b, &c, &d, &e, 30, state_context.buf.l[:]); + r2(&e, &a, &b, &c, &d, 31, state_context.buf.l[:]); + r2(&d, &e, &a, &b, &c, 32, state_context.buf.l[:]); + r2(&c, &d, &e, &a, &b, 33, state_context.buf.l[:]); + r2(&b, &c, &d, &e, &a, 34, state_context.buf.l[:]); + r2(&a, &b, &c, &d, &e, 35, state_context.buf.l[:]); + r2(&e, &a, &b, &c, &d, 36, state_context.buf.l[:]); + r2(&d, &e, &a, &b, &c, 37, state_context.buf.l[:]); + r2(&c, &d, &e, &a, &b, 38, state_context.buf.l[:]); + r2(&b, &c, &d, &e, &a, 39, state_context.buf.l[:]); + + r3(&a, &b, &c, &d, &e, 40, state_context.buf.l[:]); + r3(&e, &a, &b, &c, &d, 41, state_context.buf.l[:]); + r3(&d, &e, &a, &b, &c, 42, state_context.buf.l[:]); + r3(&c, &d, &e, &a, &b, 43, state_context.buf.l[:]); + r3(&b, &c, &d, &e, &a, 44, state_context.buf.l[:]); + r3(&a, &b, &c, &d, &e, 45, state_context.buf.l[:]); + r3(&e, &a, &b, &c, &d, 46, state_context.buf.l[:]); + r3(&d, &e, &a, &b, &c, 47, state_context.buf.l[:]); + r3(&c, &d, &e, &a, &b, 48, state_context.buf.l[:]); + r3(&b, &c, &d, &e, &a, 49, state_context.buf.l[:]); + r3(&a, &b, &c, &d, &e, 50, state_context.buf.l[:]); + r3(&e, &a, &b, &c, &d, 51, state_context.buf.l[:]); + r3(&d, &e, &a, &b, &c, 52, state_context.buf.l[:]); + r3(&c, &d, &e, &a, &b, 53, state_context.buf.l[:]); + r3(&b, &c, &d, &e, &a, 54, state_context.buf.l[:]); + r3(&a, &b, &c, &d, &e, 55, state_context.buf.l[:]); + r3(&e, &a, &b, &c, &d, 56, state_context.buf.l[:]); + r3(&d, &e, &a, &b, &c, 57, state_context.buf.l[:]); + r3(&c, &d, &e, &a, &b, 58, state_context.buf.l[:]); + r3(&b, &c, &d, &e, &a, 59, state_context.buf.l[:]); + + r4(&a, &b, &c, &d, &e, 60, state_context.buf.l[:]); + r4(&e, &a, &b, &c, &d, 61, state_context.buf.l[:]); + r4(&d, &e, &a, &b, &c, 62, state_context.buf.l[:]); + r4(&c, &d, &e, &a, &b, 63, state_context.buf.l[:]); + r4(&b, &c, &d, &e, &a, 64, state_context.buf.l[:]); + r4(&a, &b, &c, &d, &e, 65, state_context.buf.l[:]); + r4(&e, &a, &b, &c, &d, 66, state_context.buf.l[:]); + r4(&d, &e, &a, &b, &c, 67, state_context.buf.l[:]); + r4(&c, &d, &e, &a, &b, 68, state_context.buf.l[:]); + r4(&b, &c, &d, &e, &a, 69, state_context.buf.l[:]); + r4(&a, &b, &c, &d, &e, 70, state_context.buf.l[:]); + r4(&e, &a, &b, &c, &d, 71, state_context.buf.l[:]); + r4(&d, &e, &a, &b, &c, 72, state_context.buf.l[:]); + r4(&c, &d, &e, &a, &b, 73, state_context.buf.l[:]); + r4(&b, &c, &d, &e, &a, 74, state_context.buf.l[:]); + r4(&a, &b, &c, &d, &e, 75, state_context.buf.l[:]); + r4(&e, &a, &b, &c, &d, 76, state_context.buf.l[:]); + r4(&d, &e, &a, &b, &c, 77, state_context.buf.l[:]); + r4(&c, &d, &e, &a, &b, 78, state_context.buf.l[:]); + r4(&b, &c, &d, &e, &a, 79, state_context.buf.l[:]); + + state_context.state[0] += a; + state_context.state[1] += b; + state_context.state[2] += c; + state_context.state[3] += d; + state_context.state[4] += e; } -sha1_update :: proc(state_context: ^Sha1context, data: [] byte) { - - state_context.byte_count += cast(u32)len(data); - - current_data := data; +sha1_add_uncounted :: proc (state_context: ^Sha1context, data: byte) { - if state_context.buf_offset > 0 { - remainder := min(len(current_data), BLOCK_LENGTH - cast(int)state_context.buf_offset); + when ODIN_ENDIAN == "big" { + state_context.buf.c[state_context.buf_offset] = data; + } else - for i := 0; i < remainder; i += 1 { - sha1_add_uncounted(state_context, current_data[i]); - } + { + state_context.buf.c[state_context.buf_offset ~ 3] = data; + } - current_data = current_data[remainder-1:]; - } + state_context.buf_offset += 1; - for len(current_data) >= BLOCK_LENGTH { - assert(state_context.buf_offset == 0); - assert(BLOCK_LENGTH % 4 == 0); + if state_context.buf_offset == BLOCK_LENGTH { + sha1_hash_block(state_context); + state_context.buf_offset = 0; + } +} - BLOCK_LENGTH_32 :: BLOCK_LENGTH / 4; +sha1_write_byte :: proc (state_context: ^Sha1context, data: byte) { + state_context.byte_count += 1; + sha1_add_uncounted(state_context, data); +} - for i := 0; i < BLOCK_LENGTH_32; i += 1 { - n := (transmute([] u32)current_data)[i]; +sha1_update :: proc (state_context: ^Sha1context, data: []byte) { - state_context.buf.l[i] = (((n & 0xFF) << 24) | - ((n & 0xFF00) << 8) | - ((n & 0xFF0000) >> 8) | - ((n & 0xFF000000) >> 24)); - } + state_context.byte_count += cast(u32)len(data); - sha1_hash_block(state_context); + current_data := data; - current_data = current_data[BLOCK_LENGTH-1:]; - } + if state_context.buf_offset > 0 { + remainder := min(len(current_data), BLOCK_LENGTH - cast(int)state_context.buf_offset); - for c in current_data { - sha1_add_uncounted(state_context, c); - } + for i := 0; i < remainder; i += 1 { + sha1_add_uncounted(state_context, current_data[i]); + } -} + current_data = current_data[remainder - 1:]; + } -sha1_pad :: proc(state_context: ^Sha1context) { + for len(current_data) >= BLOCK_LENGTH { + assert(state_context.buf_offset == 0); + assert(BLOCK_LENGTH % 4 == 0); - sha1_add_uncounted(state_context, 0x80); + BLOCK_LENGTH_32 :: BLOCK_LENGTH / 4; - for state_context.buf_offset != 56 { - sha1_add_uncounted(state_context, 0x00); - } + for i := 0; i < BLOCK_LENGTH_32; i += 1 { + n := (transmute([]u32)current_data)[i]; - sha1_add_uncounted(state_context, 0); // We're only using 32 bit lengths - sha1_add_uncounted(state_context, 0); // But SHA-1 supports 64 bit lengths - sha1_add_uncounted(state_context, 0); // So zero pad the top bits - sha1_add_uncounted(state_context, cast(u8)(state_context.byte_count >> 29)); // Shifting to multiply by 8 - sha1_add_uncounted(state_context, cast(u8)(state_context.byte_count >> 21)); // as SHA-1 supports bitstreams as well as - sha1_add_uncounted(state_context, cast(u8)(state_context.byte_count >> 13)); // byte. - sha1_add_uncounted(state_context, cast(u8)(state_context.byte_count >> 5)); - sha1_add_uncounted(state_context, cast(u8)(state_context.byte_count << 3)); + state_context.buf.l[i] = (((n & 0xFF) << 24) | + ((n & 0xFF00) << 8) | + ((n & 0xFF0000) >> 8) | + ((n & 0xFF000000) >> 24)); + } + sha1_hash_block(state_context); + current_data = current_data[BLOCK_LENGTH - 1:]; + } + for c in current_data { + sha1_add_uncounted(state_context, c); + } } -sha1_final :: proc(state_context: ^Sha1context, result: ^[5] u32) { - sha1_pad(state_context); +sha1_pad :: proc (state_context: ^Sha1context) { - when ODIN_ENDIAN == "big" { + sha1_add_uncounted(state_context, 0x80); - for i := 0; i < 5; i += 1 { - result[i] = state_context.state[i]; - } - - } - - else { - for i := 0; i < 5; i += 1 { - result[i] = (((state_context.state[i]) << 24) & 0xff000000) | - (((state_context.state[i]) << 8) & 0x00ff0000) | - (((state_context.state[i]) >> 8) & 0x0000ff00) | - (((state_context.state[i]) >> 24) & 0x000000ff); - } - } + for state_context.buf_offset != 56 { + sha1_add_uncounted(state_context, 0x00); + } + sha1_add_uncounted(state_context, 0); // We're only using 32 bit lengths + sha1_add_uncounted(state_context, 0); // But SHA-1 supports 64 bit lengths + sha1_add_uncounted(state_context, 0); // So zero pad the top bits + sha1_add_uncounted(state_context, cast(u8)(state_context.byte_count >> 29)); // Shifting to multiply by 8 + sha1_add_uncounted(state_context, cast(u8)(state_context.byte_count >> 21)); // as SHA-1 supports bitstreams as well as + sha1_add_uncounted(state_context, cast(u8)(state_context.byte_count >> 13)); // byte. + sha1_add_uncounted(state_context, cast(u8)(state_context.byte_count >> 5)); + sha1_add_uncounted(state_context, cast(u8)(state_context.byte_count << 3)); } +sha1_final :: proc (state_context: ^Sha1context, result: ^[5]u32) { + sha1_pad(state_context); + when ODIN_ENDIAN == "big" { -sha1_hash :: proc(data: [] byte) -> [20] byte { + for i := 0; i < 5; i += 1 { + result[i] = state_context.state[i]; + } + } else - sha1_context: Sha1context; - sha1_init(&sha1_context); - sha1_update(&sha1_context, data); + { + for i := 0; i < 5; i += 1 { + result[i] = (((state_context.state[i]) << 24) & 0xff000000) | + (((state_context.state[i]) << 8) & 0x00ff0000) | + (((state_context.state[i]) >> 8) & 0x0000ff00) | + (((state_context.state[i]) >> 24) & 0x000000ff); + } + } +} - result: [20] byte; +sha1_hash :: proc (data: []byte) -> [20]byte { - sha1_final(&sha1_context, cast(^[5] u32)&result); + sha1_context: Sha1context; + sha1_init(&sha1_context); + sha1_update(&sha1_context, data); - ret: [20] byte; + result: [20]byte; - copy(ret[:], result[:]); + sha1_final(&sha1_context, cast(^[5]u32)&result); - return ret; -} + ret: [20]byte; + + copy(ret[:], result[:]); + return ret; +}
\ No newline at end of file diff --git a/src/common/track_allocator.odin b/src/common/track_allocator.odin index d2c6d24..69c0e86 100644 --- a/src/common/track_allocator.odin +++ b/src/common/track_allocator.odin @@ -1,7 +1,7 @@ package common /* - https://gist.github.com/jharler/7ee9a4d5b46e31f7f9399da49cfabe72 + https://gist.github.com/jharler/7ee9a4d5b46e31f7f9399da49cfabe72 */ import "core:mem" @@ -13,184 +13,180 @@ import "core:log" // ---------------------------------------------------------------------------------------------------- ThreadSafe_Allocator_Data :: struct { - actual_allocator : mem.Allocator, - mutex : sync.Mutex, + actual_allocator: mem.Allocator, + mutex: sync.Mutex, } // ---------------------------------------------------------------------------------------------------- threadsafe_allocator :: proc (allocator: mem.Allocator) -> mem.Allocator { - data := new(ThreadSafe_Allocator_Data); - data.actual_allocator = allocator; - sync.mutex_init(&data.mutex); + data := new(ThreadSafe_Allocator_Data); + data.actual_allocator = allocator; + sync.mutex_init(&data.mutex); - return mem.Allocator { procedure = threadsafe_allocator_proc, data = data}; + return mem.Allocator {procedure = threadsafe_allocator_proc, data = data}; } // ---------------------------------------------------------------------------------------------------- -threadsafe_allocator_proc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode, size, alignment: int, - old_memory: rawptr, old_size: int, flags : u64 = 0, loc := #caller_location) -> rawptr { +threadsafe_allocator_proc :: proc (allocator_data: rawptr, mode: mem.Allocator_Mode, size, alignment: int, +old_memory: rawptr, old_size: int, flags: u64 = 0, loc := #caller_location) -> rawptr { - data := cast(^ThreadSafe_Allocator_Data)allocator_data; + data := cast(^ThreadSafe_Allocator_Data)allocator_data; - sync.mutex_lock(&data.mutex); - defer sync.mutex_unlock(&data.mutex); + sync.mutex_lock(&data.mutex); + defer sync.mutex_unlock(&data.mutex); - return data.actual_allocator.procedure(data.actual_allocator.data, mode, size, alignment, old_memory, old_size, flags, loc); + return data.actual_allocator.procedure(data.actual_allocator.data, mode, size, alignment, old_memory, old_size, flags, loc); } // ---------------------------------------------------------------------------------------------------- Memleak_Allocator_Data :: struct { - actual_allocator : mem.Allocator, - allocations : map[rawptr] Memleak_Entry, - frees : map[rawptr] Memleak_Entry, - allocation_count : u32, - unexpected_frees : u32, - mutex : sync.Mutex, - track_frees : bool, + actual_allocator: mem.Allocator, + allocations: map[rawptr]Memleak_Entry, + frees: map[rawptr]Memleak_Entry, + allocation_count: u32, + unexpected_frees: u32, + mutex: sync.Mutex, + track_frees: bool, } // ---------------------------------------------------------------------------------------------------- Memleak_Entry :: struct { - location : runtime.Source_Code_Location, - size : int, - index : u32, + location: runtime.Source_Code_Location, + size: int, + index: u32, } // ---------------------------------------------------------------------------------------------------- -memleak_allocator_proc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode, size, alignment: int, - old_memory: rawptr, old_size: int, flags : u64 = 0, loc := #caller_location) -> rawptr { - - memleak := cast(^Memleak_Allocator_Data)allocator_data; - - sync.mutex_lock(&memleak.mutex); - defer sync.mutex_unlock(&memleak.mutex); - - if mode == .Free { - if old_memory not_in memleak.allocations { - if memleak.track_frees { - if old_memory in memleak.frees { - fmt.println(fmt.tprintf("{0}({1}:{2}) {3} freed memory already freed by this memleak allocator", loc.file_path, loc.line, loc.column, loc.procedure)); - free_loc := memleak.frees[old_memory].location; - fmt.println(fmt.tprintf("{0}({1}:{2}) {3} <<< freed here", loc.file_path, loc.line, loc.column, loc.procedure)); - } - else { - fmt.println(fmt.tprintf("{0}({1}:{2}) {3} freed memory not allocated or previously freed by this memleak allocator", loc.file_path, loc.line, loc.column, loc.procedure)); - } - } - else { - fmt.println(fmt.tprintf("{0}({1}:{2}) {3} freed memory not allocated by this memleak allocator", loc.file_path, loc.line, loc.column, loc.procedure)); - } - memleak.unexpected_frees += 1; - return nil; - } - else { - //entry := &memleak.allocations[old_memory]; - delete_key(&memleak.allocations, old_memory); - - if memleak.track_frees { - memleak.frees[old_memory] = Memleak_Entry { - location = loc, - size = size, - index = 0, - }; - } - } - } - - result := memleak.actual_allocator.procedure(memleak.actual_allocator.data, mode, size, alignment, old_memory, old_size, flags, loc); - - if mode == .Resize && result != old_memory { - delete_key(&memleak.allocations, old_memory); - } - - if mode != .Free { - // using a conditional breakpoint with memleak.allocation_count in the condition - // can be very useful for inspecting the stack trace of a particular allocation - - memleak.allocations[result] = Memleak_Entry { - location = loc, - size = size, - index = memleak.allocation_count, - }; - - memleak.allocation_count += 1; - - if memleak.track_frees { - if result in memleak.frees { - delete_key(&memleak.frees, result); - } - } - } - - return result; +memleak_allocator_proc :: proc (allocator_data: rawptr, mode: mem.Allocator_Mode, size, alignment: int, +old_memory: rawptr, old_size: int, flags: u64 = 0, loc := #caller_location) -> rawptr { + + memleak := cast(^Memleak_Allocator_Data)allocator_data; + + sync.mutex_lock(&memleak.mutex); + defer sync.mutex_unlock(&memleak.mutex); + + if mode == .Free { + if old_memory not_in memleak.allocations { + if memleak.track_frees { + if old_memory in memleak.frees { + fmt.println(fmt.tprintf("{0}({1}:{2}) {3} freed memory already freed by this memleak allocator", loc.file_path, loc.line, loc.column, loc.procedure)); + free_loc := memleak.frees[old_memory].location; + fmt.println(fmt.tprintf("{0}({1}:{2}) {3} <<< freed here", loc.file_path, loc.line, loc.column, loc.procedure)); + } else { + fmt.println(fmt.tprintf("{0}({1}:{2}) {3} freed memory not allocated or previously freed by this memleak allocator", loc.file_path, loc.line, loc.column, loc.procedure)); + } + } else { + fmt.println(fmt.tprintf("{0}({1}:{2}) {3} freed memory not allocated by this memleak allocator", loc.file_path, loc.line, loc.column, loc.procedure)); + } + memleak.unexpected_frees += 1; + return nil; + } else { + //entry := &memleak.allocations[old_memory]; + delete_key(&memleak.allocations, old_memory); + + if memleak.track_frees { + memleak.frees[old_memory] = Memleak_Entry { + location = loc, + size = size, + index = 0, + }; + } + } + } + + result := memleak.actual_allocator.procedure(memleak.actual_allocator.data, mode, size, alignment, old_memory, old_size, flags, loc); + + if mode == .Resize && result != old_memory { + delete_key(&memleak.allocations, old_memory); + } + + if mode != .Free { + // using a conditional breakpoint with memleak.allocation_count in the condition + // can be very useful for inspecting the stack trace of a particular allocation + + memleak.allocations[result] = Memleak_Entry { + location = loc, + size = size, + index = memleak.allocation_count, + }; + + memleak.allocation_count += 1; + + if memleak.track_frees { + if result in memleak.frees { + delete_key(&memleak.frees, result); + } + } + } + + return result; } // ---------------------------------------------------------------------------------------------------- memleak_allocator :: proc (track_frees: bool) -> mem.Allocator { - make([]byte, 1, context.temp_allocator); // so the temp allocation doesn't clutter our results + make([]byte, 1, context.temp_allocator); // so the temp allocation doesn't clutter our results - data := new(Memleak_Allocator_Data); - data.actual_allocator = context.allocator; - data.allocations = make(map[rawptr]Memleak_Entry); + data := new(Memleak_Allocator_Data); + data.actual_allocator = context.allocator; + data.allocations = make(map[rawptr]Memleak_Entry); - if track_frees { - data.track_frees = true; - data.frees = make(map[rawptr]Memleak_Entry); - } + if track_frees { + data.track_frees = true; + data.frees = make(map[rawptr]Memleak_Entry); + } - sync.mutex_init(&data.mutex); + sync.mutex_init(&data.mutex); - return mem.Allocator { procedure = memleak_allocator_proc, data = data}; + return mem.Allocator {procedure = memleak_allocator_proc, data = data}; } // ---------------------------------------------------------------------------------------------------- -memleak_detected_leaks :: proc() -> bool { - if context.allocator.procedure == memleak_allocator_proc { - memleak := cast(^Memleak_Allocator_Data)context.allocator.data; - return len(memleak.allocations) > 0; - } +memleak_detected_leaks :: proc () -> bool { + if context.allocator.procedure == memleak_allocator_proc { + memleak := cast(^Memleak_Allocator_Data)context.allocator.data; + return len(memleak.allocations) > 0; + } - return false; + return false; } // ---------------------------------------------------------------------------------------------------- -memleak_dump :: proc( memleak_alloc : mem.Allocator, dump_proc : proc(message:string, user_data:rawptr), user_data : rawptr) { - memleak := cast(^Memleak_Allocator_Data)memleak_alloc.data; +memleak_dump :: proc (memleak_alloc: mem.Allocator, dump_proc: proc (message: string, user_data: rawptr), user_data: rawptr) { + memleak := cast(^Memleak_Allocator_Data)memleak_alloc.data; - context.allocator = memleak.actual_allocator; + context.allocator = memleak.actual_allocator; - // check for an ignore default_temp_allocator_proc allocations - tmp_check := 0; - for _, leak in &memleak.allocations { - if leak.location.procedure == "default_temp_allocator_proc" { - tmp_check += 1; - } - } + // check for an ignore default_temp_allocator_proc allocations + tmp_check := 0; + for _, leak in &memleak.allocations { + if leak.location.procedure == "default_temp_allocator_proc" { + tmp_check += 1; + } + } + dump_proc(fmt.tprintf("{0} memory leaks detected!", len(memleak.allocations) - tmp_check), user_data); + dump_proc(fmt.tprintf("{0} unexpected frees", memleak.unexpected_frees), user_data); - dump_proc(fmt.tprintf("{0} memory leaks detected!", len(memleak.allocations) - tmp_check), user_data); - dump_proc(fmt.tprintf("{0} unexpected frees", memleak.unexpected_frees), user_data); + for _, leak in &memleak.allocations { + if leak.location.procedure != "default_temp_allocator_proc" { + dump_proc(fmt.tprintf("{0}({1}:{2}) {3} allocated {4} bytes [{5}]", leak.location.file_path, leak.location.line, leak.location.column, leak.location.procedure, leak.size, leak.index), user_data); + } + } - for _, leak in &memleak.allocations { - if leak.location.procedure != "default_temp_allocator_proc" { - dump_proc(fmt.tprintf("{0}({1}:{2}) {3} allocated {4} bytes [{5}]", leak.location.file_path, leak.location.line, leak.location.column, leak.location.procedure, leak.size, leak.index), user_data); - } - } - - context.allocator = mem.Allocator {procedure = memleak_allocator_proc, data = memleak}; + context.allocator = mem.Allocator {procedure = memleak_allocator_proc, data = memleak}; } // ---------------------------------------------------------------------------------------------------- -log_dump :: proc(message:string, user_data:rawptr) { - log.info(message); +log_dump :: proc (message: string, user_data: rawptr) { + log.info(message); }
\ No newline at end of file diff --git a/src/common/types.odin b/src/common/types.odin index 73b3f3a..4cdfc24 100644 --- a/src/common/types.odin +++ b/src/common/types.odin @@ -1,26 +1,27 @@ package common +Error :: enum -Error :: enum { - None = 0, +// Defined by JSON RPC - // Defined by JSON RPC - ParseError = -32700, - InvalidRequest = -32600, - MethodNotFound = -32601, - InvalidParams = -32602, - InternalError = -32603, - serverErrorStart = -32099, - serverErrorEnd = -32000, - ServerNotInitialized = -32002, - UnknownErrorCode = -32001, +// Defined by the protocol. - // Defined by the protocol. - RequestCancelled = -32800, - ContentModified = -32801, -}; +{ + None = 0, + ParseError = -32700, + InvalidRequest = -32600, + MethodNotFound = -32601, + InvalidParams = -32602, + InternalError = -32603, + serverErrorStart = -32099, + serverErrorEnd = -32000, + ServerNotInitialized = -32002, + UnknownErrorCode = -32001, + RequestCancelled = -32800, + ContentModified = -32801, +} WorkspaceFolder :: struct { - name: string, - uri: string, -}; + name: string, + uri: string, +}
\ No newline at end of file diff --git a/src/common/uri.odin b/src/common/uri.odin index c1d5bfd..b69ae92 100644 --- a/src/common/uri.odin +++ b/src/common/uri.odin @@ -8,164 +8,151 @@ import "core:unicode/utf8" import "core:path/filepath" Uri :: struct { - uri: string, - decode_full: string, - path: string, -}; + uri: string, + decode_full: string, + path: string, +} //Note(Daniel, This is an extremely incomplete uri parser and for now ignores fragment and query and only handles file schema) -parse_uri :: proc(value: string, allocator: mem.Allocator) -> (Uri, bool) { +parse_uri :: proc (value: string, allocator: mem.Allocator) -> (Uri, bool) { - uri: Uri; + uri: Uri; - decoded, ok := decode_percent(value, allocator); + decoded, ok := decode_percent(value, allocator); - if !ok { - return uri, false; - } + if !ok { + return uri, false; + } - starts := "file:///"; + starts := "file:///"; - start_index := len(starts); + start_index := len(starts); - if !starts_with(decoded, starts) { - return uri, false; - } + if !starts_with(decoded, starts) { + return uri, false; + } - when ODIN_OS != "windows" { - start_index -= 1; - } + when ODIN_OS != "windows" { + start_index -= 1; + } - uri.uri = strings.clone(value, allocator); - uri.decode_full = decoded; - uri.path = decoded[start_index:]; + uri.uri = strings.clone(value, allocator); + uri.decode_full = decoded; + uri.path = decoded[start_index:]; - return uri, true; + return uri, true; } - //Note(Daniel, Again some really incomplete and scuffed uri writer) -create_uri :: proc(path: string, allocator: mem.Allocator) -> Uri { - path_forward, _ := filepath.to_slash(path, context.temp_allocator); +create_uri :: proc (path: string, allocator: mem.Allocator) -> Uri { + path_forward, _ := filepath.to_slash(path, context.temp_allocator); - builder := strings.make_builder(allocator); + builder := strings.make_builder(allocator); - //bad - when ODIN_OS == "windows" { - strings.write_string(&builder, "file:///"); - } - else { - strings.write_string(&builder, "file://"); - } + //bad + when ODIN_OS == "windows" { + strings.write_string(&builder, "file:///"); + } else + { + strings.write_string(&builder, "file://"); + } - strings.write_string(&builder, encode_percent(path_forward, context.temp_allocator)); + strings.write_string(&builder, encode_percent(path_forward, context.temp_allocator)); - uri: Uri; + uri: Uri; - uri.uri = strings.to_string(builder); - uri.decode_full = strings.clone(path_forward, allocator); - uri.path = uri.decode_full; + uri.uri = strings.to_string(builder); + uri.decode_full = strings.clone(path_forward, allocator); + uri.path = uri.decode_full; - return uri; + return uri; } -delete_uri :: proc(uri: Uri) { +delete_uri :: proc (uri: Uri) { - if uri.uri != "" { - delete(uri.uri); - } + if uri.uri != "" { + delete(uri.uri); + } - if uri.decode_full != "" { - delete(uri.decode_full); - } + if uri.decode_full != "" { + delete(uri.decode_full); + } } -encode_percent :: proc(value: string, allocator: mem.Allocator) -> string { - - builder := strings.make_builder(allocator); +encode_percent :: proc (value: string, allocator: mem.Allocator) -> string { - data := transmute([]u8)value; - index: int; + builder := strings.make_builder(allocator); - for index < len(value) { + data := transmute([]u8)value; + index: int; - r, w := utf8.decode_rune(data[index:]); + for index < len(value) { - if r > 127 || r == ':'{ + r, w := utf8.decode_rune(data[index:]); - for i := 0; i < w; i += 1 { - strings.write_string(&builder, strings.concatenate({"%", fmt.tprintf("%X", data[index+i])}, - context.temp_allocator)); - } + if r > 127 || r == ':' { - } + for i := 0; i < w; i += 1 { + strings.write_string(&builder, strings.concatenate({"%", fmt.tprintf("%X", data[index + i])}, + context.temp_allocator)); + } + } else { + strings.write_byte(&builder, data[index]); + } - else { - strings.write_byte(&builder, data[index]); - } + index += w; + } - index += w; - } - - return strings.to_string(builder); + return strings.to_string(builder); } @(private) -starts_with :: proc(value: string, starts_with: string) -> bool { - - if len(value) < len(starts_with) { - return false; - } +starts_with :: proc (value: string, starts_with: string) -> bool { - for i := 0; i < len(starts_with); i += 1 { + if len(value) < len(starts_with) { + return false; + } - if value[i] != starts_with[i] { - return false; - } + for i := 0; i < len(starts_with); i += 1 { - } + if value[i] != starts_with[i] { + return false; + } + } - return true; + return true; } - @(private) -decode_percent :: proc(value: string, allocator: mem.Allocator) -> (string, bool) { +decode_percent :: proc (value: string, allocator: mem.Allocator) -> (string, bool) { - builder := strings.make_builder(allocator); + builder := strings.make_builder(allocator); - for i := 0; i < len(value); i += 1 { + for i := 0; i < len(value); i += 1 { - if value[i] == '%' { + if value[i] == '%' { - if i+2 < len(value) { + if i + 2 < len(value) { - v, ok := strconv.parse_i64_of_base(value[i+1:i+3], 16); + v, ok := strconv.parse_i64_of_base(value[i + 1:i + 3], 16); - if !ok { - strings.destroy_builder(&builder); - return "", false; - } + if !ok { + strings.destroy_builder(&builder); + return "", false; + } - strings.write_byte(&builder, cast(byte)v); + strings.write_byte(&builder, cast(byte)v); - i+= 2; - } - - else { - strings.destroy_builder(&builder); - return "", false; - } - - } - - else { - strings.write_byte(&builder, value[i]); - } - - } - - return strings.to_string(builder), true; -} + i += 2; + } else { + strings.destroy_builder(&builder); + return "", false; + } + } else { + strings.write_byte(&builder, value[i]); + } + } + return strings.to_string(builder), true; +}
\ No newline at end of file |