diff --git a/main.py b/main.py index 5d1881d..459dc62 100644 --- a/main.py +++ b/main.py @@ -351,6 +351,9 @@ class Word: inline: bool = False +_suppress_redefine_warnings = False + + @dataclass class Dictionary: words: Dict[str, Word] = field(default_factory=dict) @@ -385,7 +388,8 @@ class Dictionary: self.words[word.name] = word return word - sys.stderr.write(f"[warn] redefining word {word.name} (priority {word.priority})\n") + if not _suppress_redefine_warnings: + sys.stderr.write(f"[warn] redefining word {word.name} (priority {word.priority})\n") self.words[word.name] = word return word @@ -5374,6 +5378,7 @@ def run_repl( return False temp_dir.mkdir(parents=True, exist_ok=True) + global _suppress_redefine_warnings asm_path = temp_dir / "repl.asm" obj_path = temp_dir / "repl.o" exe_path = temp_dir / "repl.out" @@ -5530,7 +5535,11 @@ def run_repl( temp_defs_repl = [*user_defs_repl, f"word main\n {word_name}\nend"] builder_source = _repl_build_source(imports, user_defs_files, temp_defs_repl, [], True, force_synthetic=False) src_path.write_text(builder_source) - emission = compiler.compile_file(src_path, debug=debug) + _suppress_redefine_warnings = True + try: + emission = compiler.compile_file(src_path, debug=debug) + finally: + _suppress_redefine_warnings = False compiler.assembler.write_asm(emission, asm_path) run_nasm(asm_path, obj_path, debug=debug) run_linker(obj_path, exe_path, debug=debug, libs=list(libs)) @@ -5589,7 +5598,11 @@ def run_repl( ) try: snippet_src.write_text(snippet_source) - emission = compiler.compile_file(snippet_src, debug=debug) + _suppress_redefine_warnings = True + try: + emission = compiler.compile_file(snippet_src, debug=debug) + finally: + _suppress_redefine_warnings = False compiler.assembler.write_asm(emission, snippet_asm) run_nasm(snippet_asm, snippet_obj, debug=debug) run_linker(snippet_obj, snippet_exe, debug=debug, libs=list(libs)) @@ -5628,7 +5641,11 @@ def run_repl( try: src_path.write_text(source) - emission = compiler.compile_file(src_path, debug=debug) + _suppress_redefine_warnings = True + try: + emission = compiler.compile_file(src_path, debug=debug) + finally: + _suppress_redefine_warnings = False except (ParseError, CompileError, CompileTimeError) as exc: print(f"[error] {exc}") continue diff --git a/stdlib/arr.sl b/stdlib/arr.sl index 670fba1..6695486 100644 --- a/stdlib/arr.sl +++ b/stdlib/arr.sl @@ -161,25 +161,19 @@ word arr_set_static arr_item_ptr swap ! end -#arr_sort [* | arr] -> [* | arr] -# Sort built-in static array in-place in ascending order -word arr_sort - dup >r - dup arr_to_dyn - dyn_arr_sort - dup arr_data - r@ 8 + - swap - r@ @ - arr_copy_elements - arr_free - rdrop +#arr_static_free [* | arr] -> [*] +# Free built-in static array allocation produced by list literals. +word arr_static_free + dup @ 1 + 8 * free end -#dyn_arr_sort [* | dyn_arr] -> [* | dyn_arr] -:asm dyn_arr_sort { - mov rbx, [r12] ; arr - mov rcx, [rbx] ; len +#sort [*, addr | len] -> [*] +# In-place ascending sort of qword elements at `addr`. +:asm sort { + mov rcx, [r12] ; len + mov rbx, [r12 + 8] ; addr + add r12, 16 + cmp rcx, 1 jle .done @@ -191,15 +185,54 @@ end cmp rdx, rcx jge .next_outer - mov r8, [rbx + 16] ; data ptr - lea r9, [r8 + rdx*8] ; &data[j] - mov r10, [r9] ; a = data[j] - mov r11, [r9 + 8] ; b = data[j+1] - cmp r10, r11 + lea r8, [rbx + rdx*8] ; &data[j] + mov r9, [r8] ; a = data[j] + mov r10, [r8 + 8] ; b = data[j+1] + cmp r9, r10 jle .no_swap - mov [r9], r11 - mov [r9 + 8], r10 + mov [r8], r10 + mov [r8 + 8], r9 + +.no_swap: + inc rdx + jmp .inner + +.next_outer: + dec rcx + jnz .outer + +.done: + ret +} +; + +#sort8 [*, addr | len] -> [*] +# In-place ascending sort of byte elements at `addr`. +:asm sort8 { + mov rcx, [r12] ; len + mov rbx, [r12 + 8] ; addr + add r12, 16 + + cmp rcx, 1 + jle .done + + dec rcx ; outer = len - 1 +.outer: + xor rdx, rdx ; j = 0 + +.inner: + cmp rdx, rcx + jge .next_outer + + lea r8, [rbx + rdx] ; &data[j] + movzx r9, byte [r8] ; a = data[j] + movzx r10, byte [r8 + 1] ; b = data[j+1] + cmp r9, r10 + jle .no_swap + + mov byte [r8], r10b + mov byte [r8 + 1], r9b .no_swap: inc rdx @@ -225,12 +258,69 @@ word arr_clone r> end +#sorted [*, addr | len] -> [* | sorted_addr] +# Clone qword elements and return sorted copy. +word sorted + dup >r + 8 * alloc + dup >r + swap + r@ + arr_copy_elements + r> + r> + over >r + sort + r> +end + +#sorted8 [*, addr | len] -> [* | sorted_addr] +# Clone byte elements and return sorted copy. +word sorted8 + dup >r + alloc + dup >r + swap + r@ + while dup 0 > do + over c@ 3 pick swap c! + swap 1 + swap + rot 1 + -rot + 1 - + end + drop 2drop + r> + r> + over >r + sort8 + r> +end + +#arr_sort [* | arr] -> [* | arr] +# Sort built-in static array in-place in ascending order. +word arr_sort + dup >r + dup 8 + + swap @ + sort + r> +end + #arr_sorted [* | arr] -> [* | arr_sorted] word arr_sorted arr_clone arr_sort end +#dyn_arr_sort [* | dyn_arr] -> [* | dyn_arr] +word dyn_arr_sort + dup >r + dup arr_data + swap arr_len + sort + r> +end + #dyn_arr_sorted [* | dyn_arr] -> [* | dyn_arr_sorted] word dyn_arr_sorted dyn_arr_clone diff --git a/tests/arr_static_sort.sl b/tests/arr_static_sort.sl index f7261c6..610b96f 100644 --- a/tests/arr_static_sort.sl +++ b/tests/arr_static_sort.sl @@ -2,17 +2,13 @@ import ../stdlib/stdlib.sl import ../stdlib/io.sl import ../stdlib/arr.sl -word free_static - dup @ 1 + 8 * free -end - word main [ 4 1 3 2 ] dup arr_sort dup 0 swap arr_get_static puti cr dup 1 swap arr_get_static puti cr dup 2 swap arr_get_static puti cr dup 3 swap arr_get_static puti cr - free_static + arr_static_free [ 9 5 7 ] dup arr_sorted dup 0 swap arr_get_static puti cr @@ -24,6 +20,6 @@ word main dup 1 swap arr_get_static puti cr dup 2 swap arr_get_static puti cr - free_static - free_static + arr_static_free + arr_static_free end