diff --git a/build.sh b/build.sh index 4d54e42..39f42fe 100755 --- a/build.sh +++ b/build.sh @@ -3,10 +3,12 @@ mkdir build cd build -FLAGS="-nostdlib++ -fno-exceptions -fdiagnostics-absolute-paths -g -Wno-writable-strings -I../src -DDEBUG_BUILD=1" +FLAGS="-Wall -Wno-missing-braces -Wno-writable-strings -nostdlib++ -fsanitize=address -fno-exceptions -fdiagnostics-absolute-paths -g -Wno-writable-strings -I../src -DDEBUG_BUILD=1" # clang -o metaprogram $FLAGS ../src/metaprogram/metaprogram.cpp # ./metaprogram I="-I../src/external/SDL/include -I../src/external/lua/src -I../src/external/glad" clang -o te $FLAGS ../src/text_editor/text_editor.cpp $I -lSDL3 -lm -lbacktrace -cp te ../data/te \ No newline at end of file +cp te ../data/te + +# -v -Wl,--verbose \ No newline at end of file diff --git a/build_web.bat b/build_web.bat index ef933d5..5bb50ac 100755 --- a/build_web.bat +++ b/build_web.bat @@ -6,10 +6,4 @@ set flags=-Wall -Wno-missing-braces -Wno-writable-strings -nostdlib++ -fno-excep set dbg=-g -DDEBUG_BUILD=1 -gsource-map set rel=-O3 -DDEBUG_BUILD=0 -mkdir build -cd build -clang ../src/metaprogram/metaprogram.cpp -o metaprogram.exe %flags% -g -DDEBUG_BUILD=1 -I../src -metaprogram.exe -cd .. - -emcc -o text_editor.html --shell-file=data/shell.html %flags% %incs% %wasmflags% %dbg% -lm -lSDL3 src/text_editor/text_editor.cpp +emcc -o text_editor.html --shell-file=data/shell.html %flags% %incs% %wasmflags% %dbg% -lm -lSDL3 src/text_editor/text_editor.cpp diff --git a/build_web.sh b/build_web.sh index 8d72347..83111fd 100755 --- a/build_web.sh +++ b/build_web.sh @@ -1,8 +1,9 @@ #!/usr/bin/bash -mkdir build -cd build +incs="-Isrc/external/SDL/include -Isrc/external/lua/src -Isrc/external/glad -Lsrc/external/SDL/build_web -Isrc" +wasmflags="-sALLOW_MEMORY_GROWTH=1 -sMAXIMUM_MEMORY=1gb -msimd128 -sTOTAL_STACK=5MB -sINITIAL_MEMORY=256mb -sUSE_WEBGL2 -sFULL_ES3=1 -sUSE_SDL=3 -sASYNCIFY -sASSERTIONS=2" +flags="-Wall -Wno-missing-braces -Wno-writable-strings -nostdlib++ -fno-exceptions -fdiagnostics-absolute-paths" +dbg="-g -DDEBUG_BUILD=1 -gsource-map" +rel="-O3 -DDEBUG_BUILD=0" -echo todo - -cd .. \ No newline at end of file +emcc -o text_editor.html --shell-file=data/shell.html $flags $incs $wasmflags $dbg -lm -lSDL3 src/text_editor/text_editor.cpp diff --git a/src/backup/todo.txt b/src/backup/todo.txt index d683dfe..91a9c72 100644 --- a/src/backup/todo.txt +++ b/src/backup/todo.txt @@ -20,6 +20,8 @@ Debug session: - Should highlight main buffer when clicking on status? - Report errorf - use coroutine dialogs - Replace in render layer also +- BlockAllocator something is not working there which only showed after executing OpenCode on many files +- Some bad allocating happening in Clipboard for sure New UI Session - Move CommandWindow hooks to hooks diff --git a/src/basic/basic_alloc.cpp b/src/basic/basic_alloc.cpp index 3a9ca0b..744f2b5 100644 --- a/src/basic/basic_alloc.cpp +++ b/src/basic/basic_alloc.cpp @@ -268,7 +268,7 @@ void AddBlock(BlockArena *arena, size_t size = MiB(1)) { if (arena->allocator.proc == NULL) { arena->allocator = GetSystemAllocator(); } - BlockArenaNode *new_block = (BlockArenaNode *)AllocSize(arena->allocator, block_size + sizeof(BlockArenaNode) + 16); + BlockArenaNode *new_block = (BlockArenaNode *)AllocSize(arena->allocator, block_size + sizeof(BlockArenaNode)); Assert(GetAlignOffset((size_t)new_block->start, DEFAULT_ALIGNMENT) == 0); arena->start = new_block->start; new_block->end = arena->end = new_block->start + block_size; @@ -294,9 +294,7 @@ API void Release(BlockArena *arena) { next = it->next; Dealloc(arena->allocator, it); } - bool safe = arena->when_unwinding_make_sure_to_keep_last_block_alive; MemoryZero(arena, sizeof(BlockArena)); - arena->when_unwinding_make_sure_to_keep_last_block_alive = safe; } API void Unwind(BlockArena *arena, U8 *pos) { @@ -307,16 +305,11 @@ API void Unwind(BlockArena *arena, U8 *pos) { contains = true; break; } else { - bool keep = arena->when_unwinding_make_sure_to_keep_last_block_alive && arena->blocks->next == NULL; - if (keep) { - pos = arena->blocks->start; - } else { - arena->blocks = arena->blocks->next; - Dealloc(arena->allocator, it); - } + arena->blocks = arena->blocks->next; + Dealloc(arena->allocator, it); } } - Assert(contains || pos == NULL || (arena->when_unwinding_make_sure_to_keep_last_block_alive && pos == arena->blocks->start)); + Assert(contains || pos == NULL); arena->start = pos; arena->end = arena->blocks ? arena->blocks->end : NULL; } @@ -332,8 +325,11 @@ API void *BlockArenaAllocatorProc(void *object, int kind, void *p, size_t size) return NULL; } +#if OS_WASM +API void InitScratch() { +} +#else thread_local VirtualArena ScratchArenas[4]; - API void InitScratch() { for (int i = 0; i < 4; i += 1) { InitArena(&ScratchArenas[i]); @@ -362,6 +358,7 @@ API VirtualArena *GetScratchEx(VirtualArena **conflicts, int conflict_count) { Assert(unoccupied); return unoccupied; } +#endif void RunArenaTest() { Allocator memory_tracking_allocator = GetTrackingAllocator(); @@ -380,7 +377,6 @@ void RunArenaTest() { { BlockArena arena = {}; - U8 *start = arena.start; arena.allocator = memory_tracking_allocator; int *vals = (int *)PushSize(&arena, sizeof(int) * 32); for (int i = 0; i < 32; i += 1) vals[i] = i; @@ -402,7 +398,7 @@ void RunArenaTest() { U8 *p = arena.start; U8 *a = (U8 *)PushSize(&arena, KiB(32)); - U8 *b = (U8 *)PushSize(&arena, KiB(1000)); + PushSize(&arena, KiB(1000)); Assert(arena.blocks); Assert(arena.blocks->next); Assert(arena.blocks->next->next == NULL); @@ -418,7 +414,7 @@ void RunArenaTest() { { BlockArena arena = {}; arena.allocator = memory_tracking_allocator; - U8 *a = (U8 *)PushSize(&arena, KiB(2000)); + PushSize(&arena, KiB(2000)); Assert((size_t)(arena.blocks[0].end - arena.blocks[0].start) == KiB(2000)); Release(&arena); Assert(MemoryTrackingRecord.len == 0); @@ -427,15 +423,14 @@ void RunArenaTest() { { BlockArena arena = {}; arena.allocator = memory_tracking_allocator; - arena.when_unwinding_make_sure_to_keep_last_block_alive = true; PushSize(&arena, KiB(2000)); Unwind(&arena, 0); - Assert(MemoryTrackingRecord.len == 1); + Assert(MemoryTrackingRecord.len == 0); PushSize(&arena, MiB(1)); PushSize(&arena, MiB(3)); Assert(MemoryTrackingRecord.len == 2); Unwind(&arena, 0); - Assert(MemoryTrackingRecord.len == 1); + Assert(MemoryTrackingRecord.len == 0); Release(&arena); Assert(MemoryTrackingRecord.len == 0); } diff --git a/src/basic/basic_alloc.h b/src/basic/basic_alloc.h index 5a2e398..1e8c1b6 100644 --- a/src/basic/basic_alloc.h +++ b/src/basic/basic_alloc.h @@ -51,7 +51,6 @@ struct BlockArena { U8 *end; BlockArenaNode *blocks; Allocator allocator; - bool when_unwinding_make_sure_to_keep_last_block_alive; operator Allocator() { return {BlockArenaAllocatorProc, this}; } }; @@ -96,9 +95,24 @@ API void Release(VirtualArena *arena); /////////////////////////////// // Scratch +#if OS_WASM +struct Scratch { + BlockArena arena = {}; + Scratch() {} + Scratch(BlockArena *conflict) {} + Scratch(BlockArena *c1, BlockArena *c2) {} + Scratch(Allocator conflict) {} + Scratch(Allocator c1, Allocator c2) {} + ~Scratch() { Release(&arena); } + operator BlockArena *() { return &arena; } + operator Allocator() { return arena; } + private: // @Note: Disable copy constructors, cause its error prone + Scratch(Scratch &arena); + Scratch(Scratch &arena, Scratch &a2); +}; +#else extern thread_local VirtualArena ScratchArenas[4]; API VirtualArena *GetScratchEx(VirtualArena **conflicts, int conflict_count); - struct Scratch { VirtualArena *arena; U64 p; @@ -131,6 +145,7 @@ struct Scratch { Scratch(Scratch &arena); Scratch(Scratch &arena, Scratch &a2); }; +#endif const int PAGE_SIZE = 4096; const int DEFAULT_ALIGNMENT = sizeof(void *); diff --git a/src/basic/basic_os.cpp b/src/basic/basic_os.cpp index 7dba855..e5b8bb1 100644 --- a/src/basic/basic_os.cpp +++ b/src/basic/basic_os.cpp @@ -408,6 +408,7 @@ API bool IsValid(Process *process) { int res = poll(&p, 1, 0); if (res > 0) { pid_t result = waitpid(plat->pid, &status, 0); + Assert(result != -1); process->exit_code = WEXITSTATUS(status); return false; } @@ -1104,9 +1105,9 @@ API void Advance(FileIter *it) { const char *dir_char_ending = it->is_directory ? "/" : ""; const char *separator = it->path.data[it->path.len - 1] == '/' ? "" : "/"; - it->relative_path = Format(it->allocator, "%.*s%s%s%s", FmtString(it->path), separator, file->d_name, dir_char_ending); + it->relative_path = Format(it->allocator, "%S%s%s%s", it->path, separator, file->d_name, dir_char_ending); it->absolute_path = GetAbsolutePath(it->allocator, it->relative_path); - if (it->is_directory) it->absolute_path = Format(it->allocator, "%.*s/", FmtString(it->absolute_path)); + if (it->is_directory) it->absolute_path = Format(it->allocator, "%S/", it->absolute_path); it->is_valid = true; return; } diff --git a/src/external/minicoro.h b/src/external/minicoro.h index 0be8954..f770943 100644 --- a/src/external/minicoro.h +++ b/src/external/minicoro.h @@ -539,8 +539,8 @@ static void mco_dealloc(void *ptr, size_t size, void *allocator_data) { #define _MCO_USE_TSAN #endif #ifdef _MCO_USE_ASAN -void __sanitizer_start_switch_fiber(void **fake_stack_save, const void *bottom, size_t size); -void __sanitizer_finish_switch_fiber(void *fake_stack_save, const void **bottom_old, size_t *size_old); +extern "C" void __sanitizer_start_switch_fiber(void **fake_stack_save, const void *bottom, size_t size); +extern "C" void __sanitizer_finish_switch_fiber(void *fake_stack_save, const void **bottom_old, size_t *size_old); #endif #ifdef _MCO_USE_TSAN void *__tsan_get_current_fiber(void); diff --git a/src/text_editor/buffer.cpp b/src/text_editor/buffer.cpp index ef46668..1963c77 100644 --- a/src/text_editor/buffer.cpp +++ b/src/text_editor/buffer.cpp @@ -712,98 +712,52 @@ API void RawAppendf(Buffer *buffer, const char *fmt, ...) { // multicursor /////////////////////////////// -void MergeSort(int64_t Count, Caret *First, Caret *Temp) { - ProfileFunction(); - // SortKey = range.min - if (Count == 1) { - // NOTE(casey): No work to do. - } else if (Count == 2) { - Caret *EntryA = First; - Caret *EntryB = First + 1; - if (EntryA->range.min > EntryB->range.min) { - Swap(EntryA, EntryB); - } - } else { - int64_t Half0 = Count / 2; - int64_t Half1 = Count - Half0; - - Assert(Half0 >= 1); - Assert(Half1 >= 1); - - Caret *InHalf0 = First; - Caret *InHalf1 = First + Half0; - Caret *End = First + Count; - - MergeSort(Half0, InHalf0, Temp); - MergeSort(Half1, InHalf1, Temp); - - Caret *ReadHalf0 = InHalf0; - Caret *ReadHalf1 = InHalf1; - - Caret *Out = Temp; - for (int64_t Index = 0; - Index < Count; - ++Index) { - if (ReadHalf0 == InHalf1) { - *Out++ = *ReadHalf1++; - } else if (ReadHalf1 == End) { - *Out++ = *ReadHalf0++; - } else if (ReadHalf0->range.min < ReadHalf1->range.min) { - *Out++ = *ReadHalf0++; - } else { - *Out++ = *ReadHalf1++; - } - } - Assert(Out == (Temp + Count)); - Assert(ReadHalf0 == InHalf1); - Assert(ReadHalf1 == End); - - // TODO(casey): Not really necessary if we ping-pong - for (int64_t Index = 0; - Index < Count; - ++Index) { - First[Index] = Temp[Index]; - } - } +inline bool MergeSortCompare(Caret *EntryA, Caret *EntryB) { + bool result = EntryA->range.min > EntryB->range.min; + return result; } -void MergeSort(int64_t Count, Edit *First, Edit *Temp) { +inline bool MergeSortCompare(Edit *EntryA, Edit *EntryB) { + bool result = EntryA->range.min > EntryB->range.min; + return result; +} + +template +void MergeSort(int64_t Count, T *First, T *Temp) { ProfileFunction(); // SortKey = range.min if (Count == 1) { // NOTE(casey): No work to do. } else if (Count == 2) { - Edit *EntryA = First; - Edit *EntryB = First + 1; - if (EntryA->range.min > EntryB->range.min) { + T *EntryA = First; + T *EntryB = First + 1; + if (MergeSortCompare(EntryA, EntryB)) { Swap(EntryA, EntryB); } } else { - int64_t Half0 = Count / 2; - int64_t Half1 = Count - Half0; + Int Half0 = Count / 2; + Int Half1 = Count - Half0; Assert(Half0 >= 1); Assert(Half1 >= 1); - Edit *InHalf0 = First; - Edit *InHalf1 = First + Half0; - Edit *End = First + Count; + T *InHalf0 = First; + T *InHalf1 = First + Half0; + T *End = First + Count; MergeSort(Half0, InHalf0, Temp); MergeSort(Half1, InHalf1, Temp); - Edit *ReadHalf0 = InHalf0; - Edit *ReadHalf1 = InHalf1; + T *ReadHalf0 = InHalf0; + T *ReadHalf1 = InHalf1; - Edit *Out = Temp; - for (int64_t Index = 0; - Index < Count; - ++Index) { + T *Out = Temp; + for (Int Index = 0; Index < Count; ++Index) { if (ReadHalf0 == InHalf1) { *Out++ = *ReadHalf1++; } else if (ReadHalf1 == End) { *Out++ = *ReadHalf0++; - } else if (ReadHalf0->range.min < ReadHalf1->range.min) { + } else if (!MergeSortCompare(ReadHalf0, ReadHalf1)) { *Out++ = *ReadHalf0++; } else { *Out++ = *ReadHalf1++; @@ -814,9 +768,7 @@ void MergeSort(int64_t Count, Edit *First, Edit *Temp) { Assert(ReadHalf1 == End); // TODO(casey): Not really necessary if we ping-pong - for (int64_t Index = 0; - Index < Count; - ++Index) { + for (Int Index = 0; Index < Count; ++Index) { First[Index] = Temp[Index]; } } diff --git a/src/text_editor/buffer.h b/src/text_editor/buffer.h index 8f3e8a4..6cfedbb 100644 --- a/src/text_editor/buffer.h +++ b/src/text_editor/buffer.h @@ -48,8 +48,8 @@ struct Buffer { }; struct FuzzyPair { - Int index; - Int rating; + int32_t index; + int32_t rating; }; enum { @@ -130,9 +130,7 @@ API Int GetLineIndent(Buffer *buffer, Int line); API Int GetIndentAtPos(Buffer *buffer, Int pos); API Range GetIndentRangeAtPos(Buffer *buffer, Int pos); -API Int FuzzyRate(String16 string, String16 with); -API Array FuzzySearchLines(Allocator allocator, Buffer *buffer, Int line_min, Int line_max, String16 needle); -API Int FindRangeByPos(Array *ranges, Int pos); +API Int FindRangeByPos(Array *ranges, Int pos); // These don't handle history, just raw operations on buffer memory API void RawReplaceText(Buffer *buffer, Range range, String16 string); diff --git a/src/text_editor/commands.cpp b/src/text_editor/commands.cpp index 6f182d7..5fb3d05 100644 --- a/src/text_editor/commands.cpp +++ b/src/text_editor/commands.cpp @@ -669,7 +669,6 @@ String Coro_OpenCodeDir; void Coro_OpenCode(mco_coro *co) { Array dirs = {CoCurr->arena}; Add(&dirs, Coro_OpenCodeDir); - int i = 0; for (int diri = 0; diri < dirs.len; diri += 1) { for (FileIter it = IterateFiles(CoCurr->arena, dirs[diri]); IsValid(it); Advance(&it)) { bool match = false; diff --git a/src/text_editor/config.cpp b/src/text_editor/config.cpp index 26bae04..a235905 100644 --- a/src/text_editor/config.cpp +++ b/src/text_editor/config.cpp @@ -134,7 +134,6 @@ Trigger *ParseKeyChord(Lexer *lex) { Trigger *left = ParseKeyAtom(lex); EatWhitespace(lex); while (IsAlphanumeric(At(lex))) { - int op = At(lex); left = TriggerBinary(lex, left, ParseKeyChord(lex), ' '); EatWhitespace(lex); } diff --git a/src/text_editor/draw.cpp b/src/text_editor/draw.cpp index e1b72ec..2e46e33 100644 --- a/src/text_editor/draw.cpp +++ b/src/text_editor/draw.cpp @@ -294,7 +294,7 @@ void DrawWindow(Window *window, Event &event) { } // darken the inactive windows - if (!is_active) { + if (!is_active && !active_layed_out_doc) { ProfileScope(DarkenInactiveRect); SetScissor(screen_rect); DrawRect(window->total_rect, ColorInactiveWindow); diff --git a/src/text_editor/window_command.cpp b/src/text_editor/window_command.cpp index 774e49d..4739f75 100644 --- a/src/text_editor/window_command.cpp +++ b/src/text_editor/window_command.cpp @@ -27,13 +27,13 @@ void CommandWindowLayout(Rect2I *rect, Int wx, Int wy) { n->document_rect = n->total_rect = CutBottom(rect, barsize); } -Int FuzzyRate(String16 string, String16 with) { +int32_t FuzzyRate(String16 string, String16 with) { ProfileFunction(); if (with.len == 0) return 0; - Int points = 0; - Int consecutive = 0; - Int with_i = 0; - for (Int i = 0; i < string.len; i++) { + int32_t points = 0; + int32_t consecutive = 0; + int32_t with_i = 0; + for (int32_t i = 0; i < string.len; i++) { if (ToLowerCase(string.data[i]) == ToLowerCase(with[with_i])) { consecutive += 1; with_i += 1; @@ -49,33 +49,25 @@ Int FuzzyRate(String16 string, String16 with) { return points; } +inline bool MergeSortCompare(FuzzyPair *a, FuzzyPair *b) { + bool result = a->rating > b->rating; + return result; +} + Array FuzzySearchLines(Allocator allocator, Buffer *buffer, Int line_min, Int line_max, String16 needle) { ProfileFunction(); if (line_min < 0 || line_min >= buffer->line_starts.len) return {}; if (line_max < 0 || line_min > buffer->line_starts.len) return {}; Array ratings = {allocator}; + Reserve(&ratings, line_max - line_min + 4); for (Int i = line_min; i < line_max; i += 1) { String16 s = GetLineStringWithoutNL(buffer, i); - Int idx = 0; - if (Seek(s, u" || ", &idx)) { - s.len = idx; - } - s = Trim(s); - Int rating = FuzzyRate(s, needle); - Add(&ratings, {i, rating}); - } - - // bubble sort - for (Int i = 0; i < ratings.len - 1; i++) { - for (Int j = 0; j < ratings.len - 1; j++) { - if (ratings[j].rating > ratings[j + 1].rating) { - FuzzyPair temp = ratings[j]; - ratings[j] = ratings[j + 1]; - ratings[j + 1] = temp; - } - } + int32_t rating = FuzzyRate(s, needle); + Add(&ratings, {(int32_t)i, rating}); } + Array temp = Copy(allocator, ratings); + MergeSort(ratings.len, ratings.data, temp.data); return ratings; } diff --git a/src/text_editor/window_status.cpp b/src/text_editor/window_status.cpp index 5898911..8fb078a 100644 --- a/src/text_editor/window_status.cpp +++ b/src/text_editor/window_status.cpp @@ -97,7 +97,7 @@ void StatusWindowUpdate() { String16 string_to_replace = GetString(title.buffer, replace_range); if (string_to_replace != string) { SelectRange(title.view, replace_range); - Array edits = ReplaceEx(scratch, title.view, string); + ReplaceEx(scratch, title.view, string); } SelectRange(title.view, MakeRange(0));