380 lines
12 KiB
C++
380 lines
12 KiB
C++
/*
|
|
4coder_code_index.cpp - Generic code indexing system for layout, definition jumps, etc.
|
|
*/
|
|
|
|
// TOP
|
|
|
|
global Code_Index global_code_index = {};
|
|
|
|
function void
|
|
code_index_init(void){
|
|
global_code_index.mutex = system_mutex_make();
|
|
global_code_index.node_arena = make_arena_system(KB(4));
|
|
global_code_index.buffer_to_index_file =
|
|
make_table_u64_u64(global_code_index.node_arena.base_allocator, 500);
|
|
}
|
|
|
|
function Code_Index_File_Storage*
|
|
code_index__alloc_storage(void){
|
|
Code_Index_File_Storage *result = global_code_index.free_storage;
|
|
if (result == 0){
|
|
result = push_array_zero(&global_code_index.node_arena,
|
|
Code_Index_File_Storage, 1);
|
|
}
|
|
else{
|
|
sll_stack_pop(global_code_index.free_storage);
|
|
}
|
|
zdll_push_back(global_code_index.storage_first, global_code_index.storage_last,
|
|
result);
|
|
global_code_index.storage_count += 1;
|
|
return(result);
|
|
}
|
|
|
|
function void
|
|
code_index__free_storage(Code_Index_File_Storage *storage){
|
|
zdll_remove(global_code_index.storage_first, global_code_index.storage_last,
|
|
storage);
|
|
global_code_index.storage_count -= 1;
|
|
sll_stack_push(global_code_index.free_storage, storage);
|
|
}
|
|
|
|
function void
|
|
code_index_push_nest(Code_Index_Nest_List *list, Code_Index_Nest *nest){
|
|
sll_queue_push(list->first, list->last, nest);
|
|
list->count += 1;
|
|
}
|
|
|
|
function Code_Index_Nest_Ptr_Array
|
|
code_index_nest_ptr_array_from_list(Arena *arena, Code_Index_Nest_List *list){
|
|
Code_Index_Nest_Ptr_Array array = {};
|
|
array.ptrs = push_array_zero(arena, Code_Index_Nest*, list->count);
|
|
array.count = list->count;
|
|
i32 counter = 0;
|
|
for (Code_Index_Nest *node = list->first;
|
|
node != 0;
|
|
node = node->next){
|
|
array.ptrs[counter] = node;
|
|
counter += 1;
|
|
}
|
|
return(array);
|
|
}
|
|
|
|
function void
|
|
code_index_lock(void){
|
|
system_mutex_acquire(global_code_index.mutex);
|
|
}
|
|
|
|
function void
|
|
code_index_unlock(void){
|
|
system_mutex_release(global_code_index.mutex);
|
|
}
|
|
|
|
function void
|
|
code_index_set_file(Buffer_ID buffer, Arena arena, Code_Index_File *index){
|
|
Code_Index_File_Storage *storage = 0;
|
|
|
|
Table_Lookup lookup = table_lookup(&global_code_index.buffer_to_index_file,
|
|
buffer);
|
|
if (lookup.found_match){
|
|
u64 val = 0;
|
|
table_read(&global_code_index.buffer_to_index_file, lookup, &val);
|
|
storage = (Code_Index_File_Storage*)IntAsPtr(val);
|
|
linalloc_clear(&storage->arena);
|
|
}
|
|
else{
|
|
storage = code_index__alloc_storage();
|
|
table_insert(&global_code_index.buffer_to_index_file, buffer,
|
|
(u64)PtrAsInt(storage));
|
|
}
|
|
storage->arena = arena;
|
|
storage->file = index;
|
|
}
|
|
|
|
function void
|
|
code_index_erase_file(Buffer_ID buffer){
|
|
Table_Lookup lookup = table_lookup(&global_code_index.buffer_to_index_file,
|
|
buffer);
|
|
if (lookup.found_match){
|
|
u64 val = 0;
|
|
table_read(&global_code_index.buffer_to_index_file, lookup, &val);
|
|
Code_Index_File_Storage *storage = (Code_Index_File_Storage*)IntAsPtr(val);
|
|
linalloc_clear(&storage->arena);
|
|
table_erase(&global_code_index.buffer_to_index_file, lookup);
|
|
code_index__free_storage(storage);
|
|
}
|
|
}
|
|
|
|
function Code_Index_File*
|
|
code_index_get_file(Buffer_ID buffer){
|
|
Code_Index_File *result = 0;
|
|
Table_Lookup lookup = table_lookup(&global_code_index.buffer_to_index_file,
|
|
buffer);
|
|
if (lookup.found_match){
|
|
u64 val = 0;
|
|
table_read(&global_code_index.buffer_to_index_file, lookup, &val);
|
|
result = (Code_Index_File*)IntAsPtr(val);
|
|
}
|
|
return(result);
|
|
}
|
|
|
|
function Code_Index_Nest*
|
|
code_index_get_nest(Code_Index_Nest_Ptr_Array *array, i64 pos){
|
|
Code_Index_Nest *result = 0;
|
|
i32 count = array->count;
|
|
Code_Index_Nest **nest_ptrs = array->ptrs;
|
|
for (i32 i = 0; i < count; i += 1){
|
|
Code_Index_Nest *nest = nest_ptrs[i];
|
|
if (nest->open.max <= pos && pos < nest->close.min){
|
|
Code_Index_Nest *sub_nest =
|
|
code_index_get_nest(&nest->nest_array, pos);
|
|
if (sub_nest != 0){
|
|
result = sub_nest;
|
|
}
|
|
else{
|
|
result = nest;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
return(result);
|
|
}
|
|
|
|
function Code_Index_Nest*
|
|
code_index_get_nest(Code_Index_Nest *nest, i64 pos){
|
|
return(code_index_get_nest(&nest->nest_array, pos));
|
|
}
|
|
|
|
function Code_Index_Nest*
|
|
code_index_get_nest(Code_Index_File *file, i64 pos){
|
|
return(code_index_get_nest(&file->nest_array, pos));
|
|
}
|
|
|
|
////////////////////////////////
|
|
|
|
function void
|
|
generic_parse_inc(Generic_Parse_State *state){
|
|
if (!token_it_inc_all(&state->it)){
|
|
state->finished = true;
|
|
}
|
|
}
|
|
|
|
function void
|
|
generic_parse_skip_soft_tokens(Code_Index_File *index, Generic_Parse_State *state){
|
|
Token *token = token_it_read(&state->it);
|
|
for (;token != 0 && !state->finished;){
|
|
if (token->kind == TokenBaseKind_Comment){
|
|
state->handle_comment(state->app, state->arena, index, token, state->contents);
|
|
token_it_inc_non_whitespace(&state->it);
|
|
token = token_it_read(&state->it);
|
|
}
|
|
else if (token->kind == TokenBaseKind_Whitespace){
|
|
Range_i64 range = Ii64(token);
|
|
u8 *ptr = state->contents.str + range.one_past_last - 1;
|
|
for (i64 i = range.one_past_last - 1;
|
|
i >= range.first;
|
|
i -= 1, ptr -= 1){
|
|
if (*ptr == '\n'){
|
|
state->prev_line_start = ptr + 1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else{
|
|
break;
|
|
}
|
|
generic_parse_inc(state);
|
|
token = token_it_read(&state->it);
|
|
}
|
|
}
|
|
|
|
function void
|
|
generic_parse_init(Application_Links *app, Arena *arena, String_Const_u8 contents, Token_Array *tokens,
|
|
Generic_Parse_Comment_Function *handle_comment, Generic_Parse_State *state){
|
|
state->app = app;
|
|
state->arena = arena;
|
|
state->contents = contents;
|
|
state->it = token_iterator(0, tokens);
|
|
state->handle_comment = handle_comment;
|
|
state->prev_line_start = contents.str;
|
|
}
|
|
|
|
function Code_Index_Nest*
|
|
generic_parse_parenthical(Code_Index_File *index, Generic_Parse_State *state,
|
|
i64 indentation);
|
|
|
|
function Code_Index_Nest*
|
|
generic_parse_scope(Code_Index_File *index, Generic_Parse_State *state,
|
|
i64 indentation){
|
|
Token *token = token_it_read(&state->it);
|
|
Code_Index_Nest *result = push_array_zero(state->arena, Code_Index_Nest, 1);
|
|
result->kind = CodeIndexNest_Scope;
|
|
result->open = Ii64(token);
|
|
result->file = index;
|
|
|
|
result->interior_indentation = indentation + 4;
|
|
result->close_indentation = indentation;
|
|
indentation = result->interior_indentation;
|
|
|
|
generic_parse_inc(state);
|
|
for (;;){
|
|
generic_parse_skip_soft_tokens(index, state);
|
|
token = token_it_read(&state->it);
|
|
if (token == 0 || state->finished){
|
|
break;
|
|
}
|
|
|
|
if (token->kind == TokenBaseKind_ScopeOpen){
|
|
Code_Index_Nest *nest = generic_parse_scope(index, state, indentation);
|
|
nest->parent = result;
|
|
code_index_push_nest(&result->nest_list, nest);
|
|
}
|
|
else if (token->kind == TokenBaseKind_ParentheticalOpen){
|
|
Code_Index_Nest *nest = generic_parse_parenthical(index, state,
|
|
indentation);
|
|
nest->parent = result;
|
|
code_index_push_nest(&result->nest_list, nest);
|
|
}
|
|
else if (token->kind == TokenBaseKind_ScopeClose){
|
|
result->is_closed = true;
|
|
result->close = Ii64(token);
|
|
generic_parse_inc(state);
|
|
break;
|
|
}
|
|
else{
|
|
generic_parse_inc(state);
|
|
}
|
|
}
|
|
|
|
result->nest_array =
|
|
code_index_nest_ptr_array_from_list(state->arena, &result->nest_list);
|
|
|
|
return(result);
|
|
}
|
|
|
|
function Code_Index_Nest*
|
|
generic_parse_parenthical(Code_Index_File *index, Generic_Parse_State *state,
|
|
i64 indentation){
|
|
Token *token = token_it_read(&state->it);
|
|
Code_Index_Nest *result = push_array_zero(state->arena, Code_Index_Nest, 1);
|
|
result->kind = CodeIndexNest_Paren;
|
|
result->open = Ii64(token);
|
|
result->file = index;
|
|
|
|
i64 manifested_characters_on_line = 0;
|
|
{
|
|
u8 *ptr = state->prev_line_start;
|
|
u8 *end_ptr = state->contents.str + token->pos;
|
|
// NOTE(allen): Initial whitespace
|
|
for (;ptr < end_ptr; ptr += 1){
|
|
if (!character_is_whitespace(*ptr)){
|
|
break;
|
|
}
|
|
}
|
|
// NOTE(allen): Manifested characters
|
|
manifested_characters_on_line = (i64)(end_ptr - ptr) + token->size;
|
|
}
|
|
|
|
indentation += manifested_characters_on_line;
|
|
result->interior_indentation = indentation;
|
|
result->close_indentation = indentation;
|
|
|
|
generic_parse_inc(state);
|
|
for (;;){
|
|
generic_parse_skip_soft_tokens(index, state);
|
|
token = token_it_read(&state->it);
|
|
if (token == 0 || state->finished){
|
|
break;
|
|
}
|
|
|
|
if (token->kind == TokenBaseKind_ScopeOpen){
|
|
Code_Index_Nest *nest = generic_parse_scope(index, state, indentation);
|
|
nest->parent = result;
|
|
code_index_push_nest(&result->nest_list, nest);
|
|
}
|
|
else if (token->kind == TokenBaseKind_ParentheticalOpen){
|
|
Code_Index_Nest *nest = generic_parse_parenthical(index, state,
|
|
indentation);
|
|
nest->parent = result;
|
|
code_index_push_nest(&result->nest_list, nest);
|
|
}
|
|
else if (token->kind == TokenBaseKind_ParentheticalClose){
|
|
result->is_closed = true;
|
|
result->close = Ii64(token);
|
|
generic_parse_inc(state);
|
|
break;
|
|
}
|
|
else{
|
|
generic_parse_inc(state);
|
|
}
|
|
}
|
|
|
|
result->nest_array =
|
|
code_index_nest_ptr_array_from_list(state->arena, &result->nest_list);
|
|
|
|
return(result);
|
|
}
|
|
|
|
function b32
|
|
generic_parse_full_input_breaks(Code_Index_File *index, Generic_Parse_State *state, i32 limit){
|
|
b32 result = false;
|
|
|
|
i64 indentation = 0;
|
|
i64 first_index = token_it_index(&state->it);
|
|
i64 one_past_last_index = first_index + limit;
|
|
for (;;){
|
|
generic_parse_skip_soft_tokens(index, state);
|
|
Token *token = token_it_read(&state->it);
|
|
|
|
if (token == 0 || state->finished){
|
|
result = true;
|
|
break;
|
|
}
|
|
|
|
if (token->kind == TokenBaseKind_ScopeOpen){
|
|
Code_Index_Nest *nest = generic_parse_scope(index, state, indentation);
|
|
code_index_push_nest(&index->nest_list, nest);
|
|
}
|
|
else if (token->kind == TokenBaseKind_ParentheticalOpen){
|
|
Code_Index_Nest *nest = generic_parse_parenthical(index, state, indentation);
|
|
code_index_push_nest(&index->nest_list, nest);
|
|
}
|
|
else{
|
|
generic_parse_inc(state);
|
|
}
|
|
|
|
i64 index = token_it_index(&state->it);
|
|
if (index >= one_past_last_index){
|
|
token = token_it_read(&state->it);
|
|
if (token == 0){
|
|
result = true;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (result){
|
|
index->nest_array =
|
|
code_index_nest_ptr_array_from_list(state->arena, &index->nest_list);
|
|
}
|
|
|
|
return(result);
|
|
}
|
|
|
|
////////////////////////////////
|
|
|
|
function void
|
|
default_comment_index(Application_Links *app, Arena *arena, Code_Index_File *index,
|
|
Token *token, String_Const_u8 contents){
|
|
|
|
}
|
|
|
|
function void
|
|
generic_parse_init(Application_Links *app, Arena *arena, String_Const_u8 contents, Token_Array *tokens,
|
|
Generic_Parse_State *state){
|
|
generic_parse_init(app, arena, contents, tokens, default_comment_index, state);
|
|
}
|
|
|
|
|
|
// BOTTOM
|
|
|