aboutsummaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
authorDanielGavin <danielgavin5@hotmail.com>2021-03-12 16:31:09 +0100
committerDanielGavin <danielgavin5@hotmail.com>2021-03-12 16:31:09 +0100
commit00ccd7e03e17dac40efb9b34a048d968dd77c218 (patch)
tree24e9e8d9743bc3e98b63183d1f976b11ab6d93d2 /src/common
parentbaf86e02a2c45170d58ab828a13f52361129b255 (diff)
ran odinfmt on project
Diffstat (limited to 'src/common')
-rw-r--r--src/common/allocator.odin37
-rw-r--r--src/common/ast.odin1065
-rw-r--r--src/common/config.odin20
-rw-r--r--src/common/fuzzy.odin601
-rw-r--r--src/common/pool.odin66
-rw-r--r--src/common/position.odin383
-rw-r--r--src/common/pretty.odin454
-rw-r--r--src/common/sha1.odin454
-rw-r--r--src/common/track_allocator.odin248
-rw-r--r--src/common/types.odin39
-rw-r--r--src/common/uri.odin201
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