diff options
| author | DanielGavin <danielgavin5@hotmail.com> | 2020-11-29 19:25:15 +0100 |
|---|---|---|
| committer | DanielGavin <danielgavin5@hotmail.com> | 2020-11-29 19:25:15 +0100 |
| commit | 0a49dec8e063d44b86c8c28bf77dbde17cdb35c8 (patch) | |
| tree | db86b6e300135df3474eda8625f5f957c7a86a2f | |
| parent | 1b1860976d0a4ab6e23601c714df3f86f39e5691 (diff) | |
added sha1, fixed leaks, fixed crash on bad expr
| -rw-r--r-- | src/common/ast.odin | 273 | ||||
| -rw-r--r-- | src/common/sha1.odin | 309 | ||||
| -rw-r--r-- | src/common/track_allocator.odin | 7 | ||||
| -rw-r--r-- | src/index/clone.odin | 133 | ||||
| -rw-r--r-- | src/index/collector.odin | 48 | ||||
| -rw-r--r-- | src/index/memory_index.odin | 4 | ||||
| -rw-r--r-- | src/index/symbol.odin | 24 | ||||
| -rw-r--r-- | src/main.odin | 10 | ||||
| -rw-r--r-- | src/server/analysis.odin | 12 | ||||
| -rw-r--r-- | src/server/requests.odin | 5 | ||||
| -rw-r--r-- | src/server/semantic_tokens.odin | 28 |
11 files changed, 622 insertions, 231 deletions
diff --git a/src/common/ast.odin b/src/common/ast.odin index 93be57b..ca26726 100644 --- a/src/common/ast.odin +++ b/src/common/ast.odin @@ -14,7 +14,8 @@ keyword_map : map [string] bool = "i32" = true, "bool" = true, "rawptr" = true, - "any" = true}; + "any" = true, + "u32" = true}; get_ast_node_string :: proc(node: ^ast.Node, src: [] byte) -> string { return string(src[node.pos.offset:node.end.offset]); @@ -27,34 +28,34 @@ free_ast :: proc{ free_ast_comment, }; -free_ast_comment :: proc(a: ^ast.Comment_Group) { +free_ast_comment :: proc(a: ^ast.Comment_Group, allocator: mem.Allocator) { if a == nil { return; } if len(a.list) > 0 { - delete(a.list); + delete(a.list, allocator); } - free(a); + free(a, allocator); } -free_ast_array :: proc(array: $A/[]^$T) { +free_ast_array :: proc(array: $A/[]^$T, allocator: mem.Allocator) { for elem, i in array { - free_ast(elem); + free_ast(elem, allocator); } - delete(array); + delete(array, allocator); } -free_ast_dynamic_array :: proc(array: $A/[dynamic]^$T) { +free_ast_dynamic_array :: proc(array: $A/[dynamic]^$T, allocator: mem.Allocator) { for elem, i in array { - free_ast(elem); + free_ast(elem, allocator); } delete(array); } -free_ast_node :: proc(node: ^ast.Node) { +free_ast_node :: proc(node: ^ast.Node, allocator: mem.Allocator) { using ast; @@ -70,125 +71,125 @@ free_ast_node :: proc(node: ^ast.Node) { case Basic_Directive: case Basic_Lit: case Ellipsis: - free_ast(n.expr); + free_ast(n.expr, allocator); case Proc_Lit: - free_ast(n.type); - free_ast(n.body); - free_ast(n.where_clauses); + free_ast(n.type, allocator); + free_ast(n.body, allocator); + free_ast(n.where_clauses, allocator); case Comp_Lit: - free_ast(n.type); - free_ast(n.elems); + free_ast(n.type, allocator); + free_ast(n.elems, allocator); case Tag_Expr: - free_ast(n.expr); + free_ast(n.expr, allocator); case Unary_Expr: - free_ast(n.expr); + free_ast(n.expr, allocator); case Binary_Expr: - free_ast(n.left); - free_ast(n.right); + free_ast(n.left, allocator); + free_ast(n.right, allocator); case Paren_Expr: - free_ast(n.expr); + free_ast(n.expr, allocator); case Call_Expr: - free_ast(n.expr); - free_ast(n.args); + free_ast(n.expr, allocator); + free_ast(n.args, allocator); case Selector_Expr: - free_ast(n.expr); - free_ast(n.field); + free_ast(n.expr, allocator); + free_ast(n.field, allocator); case Implicit_Selector_Expr: - free_ast(n.field); + free_ast(n.field, allocator); case Index_Expr: - free_ast(n.expr); - free_ast(n.index); + free_ast(n.expr, allocator); + free_ast(n.index, allocator); case Deref_Expr: - free_ast(n.expr); + free_ast(n.expr, allocator); case Slice_Expr: - free_ast(n.expr); - free_ast(n.low); - free_ast(n.high); + free_ast(n.expr, allocator); + free_ast(n.low, allocator); + free_ast(n.high, allocator); case Field_Value: - free_ast(n.field); - free_ast(n.value); + free_ast(n.field, allocator); + free_ast(n.value, allocator); case Ternary_Expr: - free_ast(n.cond); - free_ast(n.x); - free_ast(n.y); + free_ast(n.cond, allocator); + free_ast(n.x, allocator); + free_ast(n.y, allocator); case Ternary_If_Expr: - free_ast(n.x); - free_ast(n.cond); - free_ast(n.y); + free_ast(n.x, allocator); + free_ast(n.cond, allocator); + free_ast(n.y, allocator); case Ternary_When_Expr: - free_ast(n.x); - free_ast(n.cond); - free_ast(n.y); + free_ast(n.x, allocator); + free_ast(n.cond, allocator); + free_ast(n.y, allocator); case Type_Assertion: - free_ast(n.expr); - free_ast(n.type); + free_ast(n.expr, allocator); + free_ast(n.type, allocator); case Type_Cast: - free_ast(n.type); - free_ast(n.expr); + free_ast(n.type, allocator); + free_ast(n.expr, allocator); case Auto_Cast: - free_ast(n.expr); + free_ast(n.expr, allocator); case Bad_Stmt: case Empty_Stmt: case Expr_Stmt: - free_ast(n.expr); + free_ast(n.expr, allocator); case Tag_Stmt: r := cast(^Expr_Stmt)node; - free_ast(r.expr); + free_ast(r.expr, allocator); case Assign_Stmt: - free_ast(n.lhs); - free_ast(n.rhs); + free_ast(n.lhs, allocator); + free_ast(n.rhs, allocator); case Block_Stmt: - free_ast(n.label); - free_ast(n.stmts); + free_ast(n.label, allocator); + free_ast(n.stmts, allocator); case If_Stmt: - free_ast(n.label); - free_ast(n.init); - free_ast(n.cond); - free_ast(n.body); - free_ast(n.else_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); - free_ast(n.body); - free_ast(n.else_stmt); + free_ast(n.cond, allocator); + free_ast(n.body, allocator); + free_ast(n.else_stmt, allocator); case Return_Stmt: - free_ast(n.results); + free_ast(n.results, allocator); case Defer_Stmt: - free_ast(n.stmt); + free_ast(n.stmt, allocator); case For_Stmt: - free_ast(n.label); - free_ast(n.init); - free_ast(n.cond); - free_ast(n.post); - free_ast(n.body); + 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); - free_ast(n.val0); - free_ast(n.val1); - free_ast(n.expr); - free_ast(n.body); + 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); - free_ast(n.body); + free_ast(n.list, allocator); + free_ast(n.body, allocator); case Switch_Stmt: - free_ast(n.label); - free_ast(n.init); - free_ast(n.cond); - free_ast(n.body); + 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); - free_ast(n.tag); - free_ast(n.expr); - free_ast(n.body); + 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); + free_ast(n.label, allocator); case Using_Stmt: - free_ast(n.list); + free_ast(n.list, allocator); case Bad_Decl: case Value_Decl: - free_ast(n.attributes); - free_ast(n.names); - free_ast(n.type); - free_ast(n.values); + 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: @@ -198,88 +199,88 @@ free_ast_node :: proc(node: ^ast.Node) { //free_ast(n.docs); //free_ast(n.comment); case Foreign_Block_Decl: - free_ast(n.attributes); - free_ast(n.foreign_library); - free_ast(n.body); + free_ast(n.attributes, allocator); + free_ast(n.foreign_library, allocator); + free_ast(n.body, allocator); case Foreign_Import_Decl: - free_ast(n.name); - free_ast(n.attributes); + free_ast(n.name, allocator); + free_ast(n.attributes, allocator); case Proc_Group: - free_ast(n.args); + free_ast(n.args, allocator); case Attribute: - free_ast(n.elems); + free_ast(n.elems, allocator); case Field: - free_ast(n.names); - free_ast(n.type); - free_ast(n.default_value); + 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); + free_ast(n.list, allocator); case Typeid_Type: - free_ast(n.specialization); + free_ast(n.specialization, allocator); case Helper_Type: - free_ast(n.type); + free_ast(n.type, allocator); case Distinct_Type: - free_ast(n.type); + free_ast(n.type, allocator); case Opaque_Type: - free_ast(n.type); + free_ast(n.type, allocator); case Poly_Type: - free_ast(n.type); - free_ast(n.specialization); + free_ast(n.type, allocator); + free_ast(n.specialization, allocator); case Proc_Type: - free_ast(n.params); - free_ast(n.results); + free_ast(n.params, allocator); + free_ast(n.results, allocator); case Pointer_Type: - free_ast(n.elem); + free_ast(n.elem, allocator); case Array_Type: - free_ast(n.len); - free_ast(n.elem); - free_ast(n.tag); + free_ast(n.len, allocator); + free_ast(n.elem, allocator); + free_ast(n.tag, allocator); case Dynamic_Array_Type: - free_ast(n.elem); - free_ast(n.tag); + free_ast(n.elem, allocator); + free_ast(n.tag, allocator); case Struct_Type: - free_ast(n.poly_params); - free_ast(n.align); - free_ast(n.fields); - free_ast(n.where_clauses); + 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); - free_ast(n.align); - free_ast(n.variants); - free_ast(n.where_clauses); + 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); - free_ast(n.fields); + free_ast(n.base_type, allocator); + free_ast(n.fields, allocator); case Bit_Field_Type: - free_ast(n.fields); - free_ast(n.align); + free_ast(n.fields, allocator); + free_ast(n.align, allocator); case Bit_Set_Type: - free_ast(n.elem); - free_ast(n.underlying); + free_ast(n.elem, allocator); + free_ast(n.underlying, allocator); case Map_Type: - free_ast(n.key); - free_ast(n.value); + free_ast(n.key, allocator); + free_ast(n.value, allocator); case: log.errorf("free Unhandled node kind: %T", n); } - mem.free(node); + mem.free(node, allocator); } -free_ast_file :: proc(file: ast.File) { +free_ast_file :: proc(file: ast.File, allocator := context.allocator) { for decl in file.decls { - free_ast(decl); + free_ast(decl, allocator); } - free_ast(file.pkg_decl); + free_ast(file.pkg_decl, allocator); for comment in file.comments { - free_ast(comment); + free_ast(comment, allocator); } delete(file.comments); diff --git a/src/common/sha1.odin b/src/common/sha1.odin new file mode 100644 index 0000000..d3d2119 --- /dev/null +++ b/src/common/sha1.odin @@ -0,0 +1,309 @@ +package common + +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); +} + +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); + + 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); +} + +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); +} + +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); +} + +SHA1_K0 :: 0x5a827999; +SHA1_K20 :: 0x6ed9eba1; +SHA1_K40 :: 0x8f1bbcdc; +SHA1_K60 :: 0xca62c1d6; + +SEED_0 :: 0x67452301; +SEED_1 :: 0xefcdab89; +SEED_2 :: 0x98badcfe; +SEED_3 :: 0x10325476; +SEED_4 :: 0xc3d2e1f0; + +BLOCK_LENGTH :: 64; +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; +} + +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_write_byte :: proc(state_context: ^Sha1context, data: byte) { + state_context.byte_count += 1; + sha1_add_uncounted(state_context, data); +} + +sha1_update :: proc(state_context: ^Sha1context, data: [] byte) { + + state_context.byte_count += cast(u32)len(data); + + current_data := data; + + if state_context.buf_offset > 0 { + remainder := min(len(current_data), BLOCK_LENGTH - cast(int)state_context.buf_offset); + + for i := 0; i < remainder; i += 1 { + sha1_add_uncounted(state_context, current_data[i]); + } + + current_data = current_data[remainder-1:]; + } + + for len(current_data) >= BLOCK_LENGTH { + assert(state_context.buf_offset == 0); + assert(BLOCK_LENGTH % 4 == 0); + + BLOCK_LENGTH_32 :: BLOCK_LENGTH / 4; + + for i := 0; i < BLOCK_LENGTH_32; i += 1 { + n := (transmute([] u32)current_data)[i]; + + 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_pad :: proc(state_context: ^Sha1context) { + + sha1_add_uncounted(state_context, 0x80); + + 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" { + + 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); + } + } + +} + + + +sha1_hash :: proc(data: [] byte) -> [20] byte { + + sha1_context: Sha1context; + sha1_init(&sha1_context); + sha1_update(&sha1_context, data); + + result: [20] byte; + + sha1_final(&sha1_context, cast(^[5] u32)&result); + + ret: [20] byte; + + copy(ret[:], result[:]); + + return ret; +} + diff --git a/src/common/track_allocator.odin b/src/common/track_allocator.odin index a2ad37a..c5d4452 100644 --- a/src/common/track_allocator.odin +++ b/src/common/track_allocator.odin @@ -8,6 +8,7 @@ import "core:mem" import "core:fmt" import "core:runtime" import "core:sync" +import "core:log" // ---------------------------------------------------------------------------------------------------- @@ -188,4 +189,8 @@ memleak_dump :: proc( memleak_alloc : mem.Allocator, dump_proc : proc(message:st context.allocator = mem.Allocator {procedure = memleak_allocator_proc, data = memleak}; } -// ----------------------------------------------------------------------------------------------------
\ No newline at end of file +// ---------------------------------------------------------------------------------------------------- + +log_dump :: proc(message:string, user_data:rawptr) { + log.info(message); +}
\ No newline at end of file diff --git a/src/index/clone.odin b/src/index/clone.odin index 92e79d9..19a4526 100644 --- a/src/index/clone.odin +++ b/src/index/clone.odin @@ -24,33 +24,33 @@ clone_type :: proc{ clone_dynamic_array, }; -clone_array :: proc(array: $A/[]^$T, allocator: mem.Allocator) -> A { +clone_array :: proc(array: $A/[]^$T, allocator: mem.Allocator, unique_strings: ^map[string] string) -> A { if len(array) == 0 { return nil; } res := make(A, len(array), allocator); for elem, i in array { - res[i] = auto_cast clone_type(elem, allocator); + res[i] = auto_cast clone_type(elem, allocator, unique_strings); } return res; } -clone_dynamic_array :: proc(array: $A/[dynamic]^$T, allocator: mem.Allocator) -> A { +clone_dynamic_array :: proc(array: $A/[dynamic]^$T, allocator: mem.Allocator, unique_strings: ^map[string] string) -> A { if len(array) == 0 { return nil; } res := make(A, len(array), allocator); for elem, i in array { - res[i] = auto_cast clone_type(elem, allocator); + res[i] = auto_cast clone_type(elem, allocator, unique_strings); } return res; } -clone_expr :: proc(node: ^ast.Expr, allocator: mem.Allocator) -> ^ast.Expr { - return cast(^ast.Expr)clone_node(node, allocator); +clone_expr :: proc(node: ^ast.Expr, allocator: mem.Allocator, unique_strings: ^map[string] string) -> ^ast.Expr { + return cast(^ast.Expr)clone_node(node, allocator, unique_strings); } -clone_node :: proc(node: ^ast.Node, allocator: mem.Allocator) -> ^ast.Node { +clone_node :: proc(node: ^ast.Node, allocator: mem.Allocator, unique_strings: ^map[string] string) -> ^ast.Node { using ast; @@ -81,127 +81,132 @@ clone_node :: proc(node: ^ast.Node, allocator: mem.Allocator) -> ^ast.Node { case Bad_Expr: case Ident: r := cast(^Ident)res; - r.name = strings.clone(n.name, allocator); + if unique_strings == nil { + r.name = strings.clone(n.name, allocator); + } + else { + r.name = get_index_unique_string(unique_strings, allocator, n.name); + } case Implicit: case Undef: case Basic_Lit: case Basic_Directive: case Ellipsis: r := cast(^Ellipsis)res; - r.expr = clone_type(r.expr, allocator); + r.expr = clone_type(r.expr, allocator, unique_strings); case Tag_Expr: r := cast(^Tag_Expr)res; - r.expr = clone_type(r.expr, allocator); + r.expr = clone_type(r.expr, allocator, unique_strings); case Unary_Expr: r := cast(^Unary_Expr)res; - r.expr = clone_type(r.expr, allocator); + r.expr = clone_type(r.expr, allocator, unique_strings); case Binary_Expr: r := cast(^Binary_Expr)res; - r.left = clone_type(r.left, allocator); - r.right = clone_type(r.right, allocator); + r.left = clone_type(r.left, allocator, unique_strings); + r.right = clone_type(r.right, allocator, unique_strings); case Paren_Expr: r := cast(^Paren_Expr)res; - r.expr = clone_type(r.expr, allocator); + r.expr = clone_type(r.expr, allocator, unique_strings); case Selector_Expr: r := cast(^Selector_Expr)res; - r.expr = clone_type(r.expr, allocator); - r.field = auto_cast clone_type(r.field, allocator); + r.expr = clone_type(r.expr, allocator, unique_strings); + r.field = auto_cast clone_type(r.field, allocator, unique_strings); case Implicit_Selector_Expr: r := cast(^Implicit_Selector_Expr)res; - r.field = auto_cast clone_type(r.field, allocator); + r.field = auto_cast clone_type(r.field, allocator, unique_strings); case Slice_Expr: r := cast(^Slice_Expr)res; - r.expr = clone_type(r.expr, allocator); - r.low = clone_type(r.low, allocator); - r.high = clone_type(r.high, allocator); + r.expr = clone_type(r.expr, allocator, unique_strings); + r.low = clone_type(r.low, allocator, unique_strings); + r.high = clone_type(r.high, allocator, unique_strings); case Attribute: r := cast(^Attribute)res; - r.elems = clone_type(r.elems, allocator); + r.elems = clone_type(r.elems, allocator, unique_strings); case Distinct_Type: r := cast(^Distinct_Type)res; - r.type = clone_type(r.type, allocator); + r.type = clone_type(r.type, allocator, unique_strings); case Opaque_Type: r := cast(^Opaque_Type)res; - r.type = clone_type(r.type, allocator); + r.type = clone_type(r.type, allocator, unique_strings); case Proc_Type: r := cast(^Proc_Type)res; - r.params = auto_cast clone_type(r.params, allocator); - r.results = auto_cast clone_type(r.results, allocator); + r.params = auto_cast clone_type(r.params, allocator, unique_strings); + r.results = auto_cast clone_type(r.results, allocator, unique_strings); case Pointer_Type: r := cast(^Pointer_Type)res; - r.elem = clone_type(r.elem, allocator); + r.elem = clone_type(r.elem, allocator, unique_strings); case Array_Type: r := cast(^Array_Type)res; - r.len = clone_type(r.len, allocator); - r.elem = clone_type(r.elem, allocator); - r.tag = clone_type(r.tag, allocator); + r.len = clone_type(r.len, allocator, unique_strings); + r.elem = clone_type(r.elem, allocator, unique_strings); + r.tag = clone_type(r.tag, allocator, unique_strings); case Dynamic_Array_Type: r := cast(^Dynamic_Array_Type)res; - r.elem = clone_type(r.elem, allocator); - r.tag = clone_type(r.tag, allocator); + r.elem = clone_type(r.elem, allocator, unique_strings); + r.tag = clone_type(r.tag, allocator, unique_strings); case Struct_Type: r := cast(^Struct_Type)res; - r.poly_params = auto_cast clone_type(r.poly_params, allocator); - r.align = clone_type(r.align, allocator); - r.fields = auto_cast clone_type(r.fields, allocator); - r.where_clauses = clone_type(r.where_clauses, allocator); + r.poly_params = auto_cast clone_type(r.poly_params, allocator, unique_strings); + r.align = clone_type(r.align, allocator, unique_strings); + r.fields = auto_cast clone_type(r.fields, allocator, unique_strings); + r.where_clauses = clone_type(r.where_clauses, allocator, unique_strings); case Field: r := cast(^Field)res; - r.names = clone_type(r.names, allocator); - r.type = clone_type(r.type, allocator); - r.default_value = clone_type(r.default_value, allocator); + r.names = clone_type(r.names, allocator, unique_strings); + r.type = clone_type(r.type, allocator, unique_strings); + r.default_value = clone_type(r.default_value, allocator, unique_strings); case Field_List: r := cast(^Field_List)res; - r.list = clone_type(r.list, allocator); + r.list = clone_type(r.list, allocator, unique_strings); case Field_Value: r := cast(^Field_Value)res; - r.field = clone_type(r.field, allocator); - r.value = clone_type(r.value, allocator); + r.field = clone_type(r.field, allocator, unique_strings); + r.value = clone_type(r.value, allocator, unique_strings); case Union_Type: r := cast(^Union_Type)res; - r.poly_params = auto_cast clone_type(r.poly_params, allocator); - r.align = clone_type(r.align, allocator); - r.variants = clone_type(r.variants, allocator); - r.where_clauses = clone_type(r.where_clauses, allocator); + r.poly_params = auto_cast clone_type(r.poly_params, allocator, unique_strings); + r.align = clone_type(r.align, allocator, unique_strings); + r.variants = clone_type(r.variants, allocator, unique_strings); + r.where_clauses = clone_type(r.where_clauses, allocator, unique_strings); case Enum_Type: r := cast(^Enum_Type)res; - r.base_type = clone_type(r.base_type, allocator); - r.fields = clone_type(r.fields, allocator); + r.base_type = clone_type(r.base_type, allocator, unique_strings); + r.fields = clone_type(r.fields, allocator, unique_strings); case Bit_Field_Type: r := cast(^Bit_Field_Type)res; - r.fields = clone_type(r.fields, allocator); - r.align = clone_type(r.align, allocator); + r.fields = clone_type(r.fields, allocator, unique_strings); + r.align = clone_type(r.align, allocator, unique_strings); case Bit_Set_Type: r := cast(^Bit_Set_Type)res; - r.elem = clone_type(r.elem, allocator); - r.underlying = clone_type(r.underlying, allocator); + r.elem = clone_type(r.elem, allocator, unique_strings); + r.underlying = clone_type(r.underlying, allocator, unique_strings); case Map_Type: r := cast(^Map_Type)res; - r.key = clone_type(r.key, allocator); - r.value = clone_type(r.value, allocator); + r.key = clone_type(r.key, allocator, unique_strings); + r.value = clone_type(r.value, allocator, unique_strings); case Call_Expr: r := cast(^Call_Expr)res; - r.expr = clone_type(r.expr, allocator); - r.args = clone_type(r.args, allocator); + r.expr = clone_type(r.expr, allocator, unique_strings); + r.args = clone_type(r.args, allocator, unique_strings); case Typeid_Type: r := cast(^Typeid_Type)res; - r.specialization = clone_type(r.specialization, allocator); + r.specialization = clone_type(r.specialization, allocator, unique_strings); case Ternary_When_Expr: r := cast(^Ternary_When_Expr)res; - r.x = clone_type(r.x, allocator); - r.cond = clone_type(r.cond, allocator); - r.y = clone_type(r.y, allocator); + r.x = clone_type(r.x, allocator, unique_strings); + r.cond = clone_type(r.cond, allocator, unique_strings); + r.y = clone_type(r.y, allocator, unique_strings); case Poly_Type: r := cast(^Poly_Type)res; - r.type = auto_cast clone_type(r.type, allocator); - r.specialization = clone_type(r.specialization, allocator); + r.type = auto_cast clone_type(r.type, allocator, unique_strings); + r.specialization = clone_type(r.specialization, allocator, unique_strings); case Proc_Group: r := cast(^Proc_Group)res; - r.args = clone_type(r.args, allocator); + r.args = clone_type(r.args, allocator, unique_strings); case Comp_Lit: r := cast(^Comp_Lit)res; - r.type = clone_type(r.type, allocator); - r.elems = clone_type(r.elems, allocator); + r.type = clone_type(r.type, allocator, unique_strings); + r.elems = clone_type(r.elems, allocator, unique_strings); case: log.error("Clone type Unhandled node kind: %T", n); } diff --git a/src/index/collector.odin b/src/index/collector.odin index 73ff8b9..f8dfb63 100644 --- a/src/index/collector.odin +++ b/src/index/collector.odin @@ -15,28 +15,34 @@ import "shared:common" SymbolCollection :: struct { allocator: mem.Allocator, config: ^common.Config, - symbols: map[string] Symbol, + symbols: map[uint] Symbol, unique_strings: map[string] string, //store all our strings as unique strings and reference them to save memory. }; +get_index_unique_string :: proc { + get_index_unique_string_collection, + get_index_unique_string_collection_raw, +}; -get_index_unique_string :: proc(collection: ^SymbolCollection, s: string) -> string { +get_index_unique_string_collection :: proc(collection: ^SymbolCollection, s: string) -> string { + return get_index_unique_string_collection_raw(&collection.unique_strings, collection.allocator, s); +} +get_index_unique_string_collection_raw :: proc(unique_strings: ^map[string] string, allocator: mem.Allocator, s: string) -> string { //i'm hashing this string way to much - if _, ok := collection.unique_strings[s]; !ok { - str := strings.clone(s, collection.allocator); - collection.unique_strings[str] = str; //yeah maybe I have to use some integer and hash it, tried that before but got name collisions. + if _, ok := unique_strings[s]; !ok { + str := strings.clone(s, allocator); + unique_strings[str] = str; //yeah maybe I have to use some integer and hash it, tried that before but got name collisions. } - return collection.unique_strings[s]; + return unique_strings[s]; } - make_symbol_collection :: proc(allocator := context.allocator, config: ^common.Config) -> SymbolCollection { return SymbolCollection { allocator = allocator, config = config, - symbols = make(map[string] Symbol, 16, allocator), + symbols = make(map[uint] Symbol, 16, allocator), unique_strings = make(map[string] string, 16, allocator), }; } @@ -44,8 +50,7 @@ make_symbol_collection :: proc(allocator := context.allocator, config: ^common.C delete_symbol_collection :: proc(collection: SymbolCollection) { for k, v in collection.symbols { - free_symbol(v); - delete(k, collection.allocator); + free_symbol(v, collection.allocator); } for k, v in collection.unique_strings { @@ -63,13 +68,13 @@ collect_procedure_fields :: proc(collection: ^SymbolCollection, proc_type: ^ast. args := make([dynamic] ^ast.Field, 0, collection.allocator); for ret in return_list.list { - cloned := cast(^ast.Field)clone_type(ret, collection.allocator); + cloned := cast(^ast.Field)clone_type(ret, collection.allocator, &collection.unique_strings); replace_package_alias(cloned, package_map, collection); append(&returns, cloned); } for arg in arg_list.list { - cloned := cast(^ast.Field)clone_type(arg, collection.allocator); + cloned := cast(^ast.Field)clone_type(arg, collection.allocator, &collection.unique_strings); replace_package_alias(cloned, package_map, collection); append(&args, cloned); } @@ -94,7 +99,7 @@ collect_struct_fields :: proc(collection: ^SymbolCollection, fields: ^ast.Field_ identifier := n.derived.(ast.Ident); append(&names, get_index_unique_string(collection, identifier.name)); - cloned := clone_type(field.type, collection.allocator); + cloned := clone_type(field.type, collection.allocator, &collection.unique_strings); replace_package_alias(cloned, package_map, collection); append(&types, cloned); } @@ -148,7 +153,7 @@ collect_symbols :: proc(collection: ^SymbolCollection, file: ast.File, uri: stri token = v; token_type = .Function; symbol.value = SymbolProcedureGroupValue { - group = clone_type(value_decl.values[0], collection.allocator), + group = clone_type(value_decl.values[0], collection.allocator, &collection.unique_strings), }; case ast.Struct_Type: token = v; @@ -164,9 +169,20 @@ collect_symbols :: proc(collection: ^SymbolCollection, file: ast.File, uri: stri symbol.type = token_type; symbol.uri = get_index_unique_string(collection, uri); - //id := hash.murmur64(transmute([]u8)strings.concatenate({symbol.scope, name}, context.temp_allocator)); + cat := strings.concatenate({symbol.scope, name}, context.temp_allocator); + + id := get_symbol_id(cat); + + //right now i'm not checking comments whether is for windows, linux, etc, and some packages do not specify that(os) + if v, ok := collection.symbols[id]; !ok { + collection.symbols[id] = symbol; + //fmt.printf("FAILED COLLOSION! %v %v \n", id, cat); + } + + else { + free_symbol(symbol, collection.allocator); + } - collection.symbols[strings.concatenate({symbol.scope, name}, collection.allocator)] = symbol; } } diff --git a/src/index/memory_index.odin b/src/index/memory_index.odin index e99d759..05de53b 100644 --- a/src/index/memory_index.odin +++ b/src/index/memory_index.odin @@ -28,7 +28,9 @@ make_memory_index :: proc(collection: SymbolCollection) -> MemoryIndex { memory_index_lookup :: proc(index: ^MemoryIndex, name: string, scope: string) -> (Symbol, bool) { //hashed := hash.murmur64(transmute([]u8)strings.concatenate({scope, name}, context.temp_allocator)); - return index.collection.symbols[strings.concatenate({scope, name}, context.temp_allocator)]; + + id := get_symbol_id(strings.concatenate({scope, name}, context.temp_allocator)); + return index.collection.symbols[id]; } memory_index_fuzzy_search :: proc(index: ^MemoryIndex, name: string, scope: [] string) -> ([] Symbol, bool) { diff --git a/src/index/symbol.odin b/src/index/symbol.odin index 8c672d9..6630015 100644 --- a/src/index/symbol.odin +++ b/src/index/symbol.odin @@ -7,6 +7,7 @@ import "core:mem" import "core:fmt" import "core:path/filepath" import "core:path" +import "core:slice" import "shared:common" @@ -89,16 +90,29 @@ SymbolType :: enum { Struct = 22, }; -free_symbol :: proc(symbol: Symbol) { +free_symbol :: proc(symbol: Symbol, allocator: mem.Allocator) { #partial switch v in symbol.value { case SymbolProcedureValue: - common.free_ast(v.return_types); - common.free_ast(v.arg_types); + common.free_ast(v.return_types, allocator); + common.free_ast(v.arg_types, allocator); case SymbolStructValue: - common.free_ast(v.types); + delete(v.names, allocator); + common.free_ast(v.types, allocator); case SymbolGenericValue: - common.free_ast(v.expr); + common.free_ast(v.expr, allocator); + case SymbolProcedureGroupValue: + common.free_ast(v.group, allocator); + case SymbolEnumValue: + delete(v.names, allocator); + case SymbolUnionValue: + delete(v.names, allocator); } +} + +get_symbol_id :: proc(str: string) -> uint { + ret := common.sha1_hash(transmute([]byte)str); + r := cast(^uint)slice.first_ptr(ret[:]); + return r^; }
\ No newline at end of file diff --git a/src/main.odin b/src/main.odin index 6246ba0..7518454 100644 --- a/src/main.odin +++ b/src/main.odin @@ -50,7 +50,6 @@ run :: proc(reader: ^server.Reader, writer: ^server.Writer) { return; } - value: json.Value; value, success = server.read_and_parse_body(reader, header); @@ -69,12 +68,21 @@ run :: proc(reader: ^server.Reader, writer: ^server.Writer) { free_all(context.temp_allocator); } + for k, v in config.collections { + delete(k); + delete(v); + } + delete(config.collections); delete(config.workspace_folders); server.document_storage_shutdown(); index.free_static_index(); + + //common.memleak_dump(tracking_allocator, common.log_dump, nil); + + } end :: proc() { diff --git a/src/server/analysis.odin b/src/server/analysis.odin index e026023..4f021b7 100644 --- a/src/server/analysis.odin +++ b/src/server/analysis.odin @@ -348,7 +348,7 @@ resolve_generic_function_symbol :: proc(ast_context: ^AstContext, params: []^ast } if ident, ok := result.type.derived.(Ident); ok { - field := cast(^Field)index.clone_node(result, context.temp_allocator); + field := cast(^Field)index.clone_node(result, context.temp_allocator, nil); if m := &poly_map[ident.name]; m != nil { field.type = poly_map[ident.name]; @@ -938,7 +938,7 @@ make_symbol_struct_from_ast :: proc(ast_context: ^AstContext, v: ast.Struct_Type } else { - append(&types, index.clone_type(field.type, context.temp_allocator)); + append(&types, index.clone_type(field.type, context.temp_allocator, nil)); } } } @@ -1558,7 +1558,7 @@ get_completion_list :: proc(document: ^Document, position: common.Position) -> ( //if there is no field we had to recover from bad expr and create a node (remove when parser can accept temp_allocator) if position_context.field == nil { - common.free_ast(position_context.selector); + common.free_ast(position_context.selector, context.allocator); } list.items = items[:]; @@ -1725,7 +1725,11 @@ get_document_position_node :: proc(node: ^ast.Node, position_context: ^DocumentP str := position_context.file.src[node.pos.offset:max(0, node.end.offset-1)]; - p := parser.default_parser(); + p := parser.Parser { + err = parser_warning_handler, //empty + warn = parser_warning_handler, //empty + file = &position_context.file, + }; tokenizer.init(&p.tok, str, position_context.file.fullpath); diff --git a/src/server/requests.odin b/src/server/requests.odin index 4eed483..149ea3a 100644 --- a/src/server/requests.odin +++ b/src/server/requests.odin @@ -269,8 +269,8 @@ request_initialize :: proc(params: json.Value, id: RequestId, config: ^common.Co token_type := type_info_of(SemanticTokenTypes).variant.(runtime.Type_Info_Named).base.variant.(runtime.Type_Info_Enum); token_modifier := type_info_of(SemanticTokenModifiers).variant.(runtime.Type_Info_Named).base.variant.(runtime.Type_Info_Enum); - token_types := make([] string, len(token_type.names)); - token_modifiers := make([] string, len(token_modifier.names)); + token_types := make([] string, len(token_type.names), context.temp_allocator); + token_modifiers := make([] string, len(token_modifier.names), context.temp_allocator); for name, i in token_type.names { token_types[i] = strings.to_lower(name, context.temp_allocator); @@ -350,7 +350,6 @@ request_definition :: proc(params: json.Value, id: RequestId, config: ^common.Co return .ParseError; } - document := document_get(definition_params.textDocument.uri); if document == nil { diff --git a/src/server/semantic_tokens.odin b/src/server/semantic_tokens.odin index d374cc0..03f739b 100644 --- a/src/server/semantic_tokens.odin +++ b/src/server/semantic_tokens.odin @@ -63,10 +63,38 @@ SemanticTokens :: struct { data: [] uint, }; +SemanticTokenInternal :: struct { + line: uint, + column: uint, + length: uint, +}; + + +convert_to_finished_tokens :: proc(tokens: [dynamic]SemanticTokenInternal) -> [] SemanticTokens { + return {}; +} + get_semantic_tokens :: proc(document: ^Document) -> [] SemanticTokens { + tokens := make([dynamic]SemanticTokenInternal, context.temp_allocator); + /* + Temp parse the document again, right now there is too many leaks that need to be fixued in the parser. + */ return {}; } + + +/* +extract_semantic_tokens :: proc { + extract_semantic_tokens_node, + extract_semantic_tokens_dynamic_array, + extract_semantic_tokens_array, +}; + +extract_semantic_tokens_node :: proc() { + +} +*/
\ No newline at end of file |