diff --git a/examples/euler13.zr b/examples/euler13.zr index 27cf2d0..12b5d88 100644 --- a/examples/euler13.zr +++ b/examples/euler13.zr @@ -1,5 +1,5 @@ func main[] : I64 37107287533 + 46376937677 + 74324986199 + 91942213363 + 23067588207 + 89261670696 + 28112879812 + 44274228917 + 47451445736 + 70386486105 + 62176457141 + 64906352462 + 92575867718 + 58203565325 + 80181199384 + 35398664372 + 86515506006 + 71693888707 + 54370070576 + 53282654108 + 36123272525 + 45876576172 + 17423706905 + 81142660418 + 51934325451 + 62467221648 + 15732444386 + 55037687525 + 18336384825 + 80386287592 + 78182833757 + 16726320100 + 48403098129 + 87086987551 + 59959406895 + 69793950679 + 41052684708 + 65378607361 + 35829035317 + 94953759765 + 88902802571 + 25267680276 + 36270218540 + 24074486908 + 91430288197 + 34413065578 + 23053081172 + 11487696932 + 63783299490 + 67720186971 + 95548255300 + 76085327132 + 37774242535 + 23701913275 + 29798860272 + 18495701454 + 38298203783 + 34829543829 + 40957953066 + 29746152185 + 41698116222 + 62467957194 + 23189706772 + 86188088225 + 11306739708 + 82959174767 + 97623331044 + 42846280183 + 55121603546 + 32238195734 + 75506164965 + 62177842752 + 32924185707 + 99518671430 + 73267460800 + 76841822524 + 97142617910 + 87783646182 + 10848802521 + 71329612474 + 62184073572 + 66627891981 + 60661826293 + 85786944089 + 66024396409 + 64913982680 + 16730939319 + 94809377245 + 78639167021 + 15368713711 + 40789923115 + 44889911501 + 41503128880 + 81234880673 + 82616570773 + 22918802058 + 77158542502 + 72107838435 + 20849603980 + 53503534226 |> I64.to_string() - |> substr(0, 10) + |> String.substr(0, 10) |> print() \ No newline at end of file diff --git a/examples/quicksort.zr b/examples/quicksort.zr new file mode 100644 index 0000000..ae3e0a7 --- /dev/null +++ b/examples/quicksort.zr @@ -0,0 +1,46 @@ +func quicksort[arr: Array] : I64 + do_quicksort(arr, 0, Array.size(arr)-1) + +func do_quicksort[arr: Array, low: I64, high: I64] : I64 + if low < high + let i: I64 = partition(arr, low, high) + do_quicksort(arr, low, i - 1) + do_quicksort(arr, i + 1, high) + +func partition[arr: Array, low: I64, high: I64] : I64 + let pivot: I64 = Array.nth(arr, high) + let i: I64 = low - 1 + for j in low:high + if Array.nth(arr, j) <= pivot + i = i + 1 + let temp: I64 = Array.nth(arr, i) + Array.set(arr, i, Array.nth(arr, j)) + Array.set(arr, j, temp) + let temp: I64 = Array.nth(arr, i + 1) + Array.set(arr, i + 1, Array.nth(arr, high)) + Array.set(arr, high, temp) + return i + 1 + +func main[] : I64 + let arr: Array = Array.new() + Array.push(arr, 340) + Array.push(arr, 252) + Array.push(arr, 352) + Array.push(arr, 117) + Array.push(arr, 650) + Array.push(arr, 652) + Array.push(arr, 322) + Array.push(arr, 175) + Array.push(arr, 714) + Array.push(arr, 268) + Array.push(arr, 725) + Array.push(arr, 664) + + for i in 0:Array.size(arr) + print_i64(Array.nth(arr, i)) + print("------------") + + quicksort(arr) + + for i in 0:Array.size(arr) + print_i64(Array.nth(arr, i)) \ No newline at end of file diff --git a/examples/rule110.zr b/examples/rule110.zr index 02f349a..3293302 100644 --- a/examples/rule110.zr +++ b/examples/rule110.zr @@ -19,9 +19,9 @@ func to_str[state: Array]: String let o: String = "" for i in 0:Array.size(state) if Array.nth(state, i) - o = concat(o, "#") + o = String.concat(o, "#") else - o = concat(o, " ") + o = String.concat(o, " ") return o func main[] : I64 diff --git a/examples/strings.zr b/examples/strings.zr index ad28f4f..70d7b61 100644 --- a/examples/strings.zr +++ b/examples/strings.zr @@ -1,7 +1,7 @@ func main[] : I64 let a: String = I64.to_string(58394) print_i64(strlen(a)) - let b: String = concat(a, "test") + let b: String = String.concat(a, "test") print_i64(strlen(b)) free(a) free(b) \ No newline at end of file diff --git a/src/builtin.s b/src/builtin.s new file mode 100644 index 0000000..3cd13c4 --- /dev/null +++ b/src/builtin.s @@ -0,0 +1,152 @@ +String.nth: + movzx rax, byte [rdi + rsi] + ret + +String.set: + mov [rdi + rsi], dl + ret + +OS.time: + push rbx + sub rsp, 16 + mov rbx, rsp + mov rdi, rbx + xor esi, esi + call gettimeofday + imul rcx, qword [rbx], 1000 + mov rax, qword [rbx+8] + mov esi, 1000 + cqo + idiv rsi + add rax, rcx + add rsp, 16 + pop rbx + ret + +OS.listdir: + push r14 + push rbx + push rax + mov r14, rdi + call Array.new + mov rbx, rax + mov rdi, r14 + call opendir + mov r14, rax +.LBB5_1: + mov rdi, r14 + call readdir + test rax, rax + je .LBB5_7 + cmp byte [rax+19], 46 + jne .LBB5_6 + movzx ecx, byte [rax+20] + test ecx, ecx + je .LBB5_1 + cmp ecx, 46 + jne .LBB5_6 + cmp byte [rax+21], 0 + je .LBB5_1 +.LBB5_6: + add rax, 19 + mov rdi, rax + call strdup + mov rsi, rax + mov rdi, rbx + call Array.push + jmp .LBB5_1 +.LBB5_7: + mov rdi, r14 + call closedir + mov rax, rbx + add rsp, 8 + pop rbx + pop r14 + ret + +Array.new: + mov rdi, 1 + mov rsi, 24 + jmp calloc + +Array.nth: + mov rax, [rdi] + mov rax, [rax + rsi*8] + ret + +Array.set: + mov rax, [rdi] + mov [rax + rsi*8], rdx + ret + +Array.push: + push r14 + push rbx + push rax + mov r14, rsi + mov rbx, rdi + mov rax, [rdi] + mov rcx, [rdi + 16] + cmp rcx, [rdi + 8] + jne .no_realloc + lea rdx, [rcx + rcx] + mov rsi, 4 + test rcx, rcx + cmovnz rsi, rdx + mov [rbx + 8], rsi + shl rsi, 3 + mov rdi, rax + call realloc + mov [rbx], rax + mov rcx, [rbx + 16] +.no_realloc: + mov [rax + rcx*8], r14 + inc qword [rbx + 16] + add rsp, 8 + pop rbx + pop r14 + ret + +Array.size: + mov rax, [rdi + 16] + ret + +Array.free: + push rbx + mov rbx, rdi + mov rdi, [rdi] + call free + mov rdi, rbx + pop rbx + jmp free + +Math.isqrt: + xor rax, rax + mov rcx, 1 + mov rbx, rdi + shl rcx, 62 +.isqrt.1: + cmp rcx, 0 + je .isqrt.5 + cmp rcx, rbx + jbe .isqrt.2 + shr rcx, 2 + jmp .isqrt.1 +.isqrt.2: + cmp rcx, 0 + je .isqrt.5 + mov rdx, rax + add rdx, rcx + cmp rbx, rdx + jb .isqrt.3 + sub rbx, rdx + shr rax, 1 + add rax, rcx + jmp .isqrt.4 +.isqrt.3: + shr rax, 1 +.isqrt.4: + shr rcx, 2 + jmp .isqrt.2 +.isqrt.5: + ret \ No newline at end of file diff --git a/src/codegen_x86_64.rs b/src/codegen_x86_64.rs index d4fd18b..2b8e1d6 100644 --- a/src/codegen_x86_64.rs +++ b/src/codegen_x86_64.rs @@ -102,6 +102,7 @@ extern realloc extern free extern printf extern sprintf +extern strtol extern strlen extern strcmp extern strcat @@ -113,6 +114,8 @@ extern fopen extern fseek extern ftell extern fread +extern fwrite +extern fclose extern rewind extern system extern opendir @@ -120,156 +123,9 @@ extern readdir extern closedir extern exit extern gettimeofday - -String.nth: - movzx rax, byte [rdi + rsi] - ret - -String.set: - mov [rdi + rsi], dl - ret - -OS.time: - push rbx - sub rsp, 16 - mov rbx, rsp - mov rdi, rbx - xor esi, esi - call gettimeofday - imul rcx, qword [rbx], 1000 - mov rax, qword [rbx+8] - mov esi, 1000 - cqo - idiv rsi - add rax, rcx - add rsp, 16 - pop rbx - ret - -OS.listdir: - push r14 - push rbx - push rax - mov r14, rdi - call Array.new - mov rbx, rax - mov rdi, r14 - call opendir - mov r14, rax -.LBB5_1: - mov rdi, r14 - call readdir - test rax, rax - je .LBB5_7 - cmp byte [rax+19], 46 - jne .LBB5_6 - movzx ecx, byte [rax+20] - test ecx, ecx - je .LBB5_1 - cmp ecx, 46 - jne .LBB5_6 - cmp byte [rax+21], 0 - je .LBB5_1 -.LBB5_6: - add rax, 19 - mov rdi, rax - call strdup - mov rsi, rax - mov rdi, rbx - call Array.push - jmp .LBB5_1 -.LBB5_7: - mov rdi, r14 - call closedir - mov rax, rbx - add rsp, 8 - pop rbx - pop r14 - ret - -Array.new: - mov rdi, 1 - mov rsi, 24 - jmp calloc - -Array.nth: - mov rax, [rdi] - mov rax, [rax + rsi*8] - ret - -Array.push: - push r14 - push rbx - push rax - mov r14, rsi - mov rbx, rdi - mov rax, [rdi] - mov rcx, [rdi + 16] - cmp rcx, [rdi + 8] - jne .no_realloc - lea rdx, [rcx + rcx] - mov rsi, 4 - test rcx, rcx - cmovnz rsi, rdx - mov [rbx + 8], rsi - shl rsi, 3 - mov rdi, rax - call realloc - mov [rbx], rax - mov rcx, [rbx + 16] -.no_realloc: - mov [rax + rcx*8], r14 - inc qword [rbx + 16] - add rsp, 8 - pop rbx - pop r14 - ret - -Array.size: - mov rax, [rdi + 16] - ret - -Array.free: - push rbx - mov rbx, rdi - mov rdi, [rdi] - call free - mov rdi, rbx - pop rbx - jmp free - -Math.isqrt: - xor rax, rax - mov rcx, 1 - mov rbx, rdi - shl rcx, 62 -.isqrt.1: - cmp rcx, 0 - je .isqrt.5 - cmp rcx, rbx - jbe .isqrt.2 - shr rcx, 2 - jmp .isqrt.1 -.isqrt.2: - cmp rcx, 0 - je .isqrt.5 - mov rdx, rax - add rdx, rcx - cmp rbx, rdx - jb .isqrt.3 - sub rbx, rdx - shr rax, 1 - add rax, rcx - jmp .isqrt.4 -.isqrt.3: - shr rax, 1 -.isqrt.4: - shr rcx, 2 - jmp .isqrt.2 -.isqrt.5: - ret ", ); + emit!(&mut self.output, "{}", include_str!("builtin.s")); Ok(()) } diff --git a/src/main.rs b/src/main.rs index db946c7..f5b91c5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -44,6 +44,7 @@ fn compile_file(path: String) -> Result<(), ZernError> { compile_file_to(&mut codegen, filename, source)?; codegen.emit_epilogue()?; + // TODO if fs::write("out.s", codegen.get_output()).is_err() { eprintln!("\x1b[91mERROR\x1b[0m: failed to write to out.s"); process::exit(1); diff --git a/src/std.zr b/src/std.zr index 6b8556c..0f08fb2 100644 --- a/src/std.zr +++ b/src/std.zr @@ -8,13 +8,13 @@ func print[x: String] : I64 func print_i64[x: I64] : I64 printf("%ld\n", x) -func concat[a: String, b: String] : String +func String.concat[a: String, b: String] : String let c: String = malloc(strlen(a) + strlen(b) + 1) strcpy(c, a) strcat(c, b) return c -func substr[s: String, start: I64, length: I64] : String +func String.substr[s: String, start: I64, length: I64] : String let out: String = malloc(length + 1) strlcpy(out, s + start, length + 1) return out @@ -42,8 +42,17 @@ func IO.read_file[path: String]: String let n: I64 = fread(buffer, 1, size, file) String.set(buffer, n, 0) + fclose(file) return buffer +func IO.write_file[path: String, content: String] : I64 + let file: Ptr = fopen(path, "wb") + if !file + panic("failed to open file") + + fwrite(content, 1, strlen(content), file) + fclose(file) + func Char.to_i64[c: Char]: I64 return c - 48 @@ -52,6 +61,9 @@ func I64.to_string[n: I64] : String sprintf(x, "%ld", n) return x +func I64.parse[s: String] : I64 + return strtol(s, 0, 0) + func Math.gcd[a: I64, b: I64] : I64 while b != 0 let tmp: I64 = b diff --git a/test.zr b/test.zr index d1f2532..4359b0e 100644 --- a/test.zr +++ b/test.zr @@ -1,6 +1,6 @@ func run_test[x: String] : I64 printf("\033[93mBuilding %s...\033[0m", x) - let cmd: String = concat("./target/release/zern examples/", x) + let cmd: String = String.concat("./target/release/zern examples/", x) let build_start_time: I64 = OS.time() if system(cmd) != 0