From a0bee3f5ca2fa45df5c261e0ca067eae4db43dec Mon Sep 17 00:00:00 2001 From: Toni Date: Mon, 30 Jun 2025 13:59:17 +0200 Subject: [PATCH] brainfuck interpreter --- examples/arrays.zr | 5 ----- examples/brainfuck.zr | 45 ++++++++++++++++++++++++++++++++++++++++++ examples/tcp_client.zr | 2 +- examples/tcp_server.zr | 2 +- src/codegen_x86_64.rs | 11 +++++++++-- src/std.zr | 8 ++++---- test.zr | 17 ++++++++-------- 7 files changed, 68 insertions(+), 22 deletions(-) delete mode 100644 examples/arrays.zr create mode 100644 examples/brainfuck.zr diff --git a/examples/arrays.zr b/examples/arrays.zr deleted file mode 100644 index ceacf89..0000000 --- a/examples/arrays.zr +++ /dev/null @@ -1,5 +0,0 @@ -func main[] : I64 - let xs: Array = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] - for x in 0..3 - for y in 0..3 - print_i64(xs[y][x]) \ No newline at end of file diff --git a/examples/brainfuck.zr b/examples/brainfuck.zr new file mode 100644 index 0000000..f076fb1 --- /dev/null +++ b/examples/brainfuck.zr @@ -0,0 +1,45 @@ +func main[] : I64 + let src: String = "++++++++[>+>++++<<-]>++>>+<[-[>>+<<-]+>>]>+[-<<<[->[+[-]+>++>>>-<<]<[<]>>++++++[<<+++++>>-]+<<++.[-]<<]>.>+[>>]>+]" + let src_len: I64 = strlen(src) + let i: I64 = 0 + + let memory: Ptr = calloc(1, 30000) + let p: I64 = 0 + + while i < src_len + let op: U8 = String.nth(src, i) + + if op == '>' + p = p + 1 + else if op == '<' + p = p - 1 + else if op == '+' + String.set(memory, p, String.nth(memory, p)+1) + else if op == '-' + String.set(memory, p, String.nth(memory, p)-1) + else if op == '.' + printf("%c", String.nth(memory, p)) + else if op == ',' + String.set(memory, p, getchar()) + else if op == '[' + if !String.nth(memory, p) + i = i + 1 + let opened: I64 = 0 + while i < src_len && !(String.nth(src, i) == ']' && !opened) + if String.nth(src, i) == '[' + opened = opened + 1 + else if String.nth(src, i) == ']' + opened = opened - 1 + i = i + 1 + else if op == ']' + if String.nth(memory, p) + i = i - 1 + let closed: I64 = 0 + while i >= 0 && !(String.nth(src, i) == '[' && !closed) + if String.nth(src, i) == ']' + closed = closed + 1 + else if String.nth(src, i) == '[' + closed = closed - 1 + i = i - 1 + + i = i + 1 \ No newline at end of file diff --git a/examples/tcp_client.zr b/examples/tcp_client.zr index d6a013f..f07ba39 100644 --- a/examples/tcp_client.zr +++ b/examples/tcp_client.zr @@ -4,7 +4,7 @@ func main[] : I64 panic("socket() failed") let port: I64 = 80 - let sa: Ptr = calloc(16) + let sa: Ptr = calloc(1, 16) String.set(sa, 0, 2) String.set(sa, 1, 0) String.set(sa, 2, Bit.rshift(port, 8) && 255) diff --git a/examples/tcp_server.zr b/examples/tcp_server.zr index ded97d6..fd2fea7 100644 --- a/examples/tcp_server.zr +++ b/examples/tcp_server.zr @@ -4,7 +4,7 @@ func main[] : I64 panic("socket() failed") let port: I64 = 8080 - let sa: Ptr = calloc(16) + let sa: Ptr = calloc(1, 16) String.set(sa, 0, 2) String.set(sa, 1, 0) String.set(sa, 2, Bit.rshift(port, 8) && 255) diff --git a/src/codegen_x86_64.rs b/src/codegen_x86_64.rs index 7372539..1f48174 100644 --- a/src/codegen_x86_64.rs +++ b/src/codegen_x86_64.rs @@ -133,9 +133,16 @@ extern close extern bind extern listen extern accept +extern getchar -section .text._builtin_deref -_builtin_deref: +section .text._builtin_deref8 +_builtin_deref8: + xor rax, rax + mov al, byte [rdi] + ret + +section .text._builtin_deref64 +_builtin_deref64: mov rax, qword [rdi] ret diff --git a/src/std.zr b/src/std.zr index 0b3c273..c118a68 100644 --- a/src/std.zr +++ b/src/std.zr @@ -9,7 +9,7 @@ func print_i64[x: I64] : I64 printf("%ld\n", x) func String.nth[s: String, n: I64] : U8 - return _builtin_deref(s + n) + return _builtin_deref8(s + n) func String.set[s: String, n: I64, c: U8] : I64 _builtin_string_set(s, n, c) @@ -169,7 +169,7 @@ func Math.urandom[]: I64 let file: Ptr = fopen("/dev/urandom", "rb") fread(buffer, 8, 1, file) fclose(file) - let n: I64 = _builtin_deref(buffer) + let n: I64 = _builtin_deref64(buffer) free(buffer) return n @@ -188,8 +188,8 @@ func Array.size[xs: Array] : I64 func OS.time[] : I64 let tv: Ptr = malloc(16) gettimeofday(tv, 0) - let seconds: I64 = _builtin_deref(tv) - let microseconds: I64 = _builtin_deref(tv+8) + let seconds: I64 = _builtin_deref64(tv) + let microseconds: I64 = _builtin_deref64(tv+8) free(tv) return seconds * 1000 + microseconds / 1000 diff --git a/test.zr b/test.zr index 5f2bc80..9d2fe03 100644 --- a/test.zr +++ b/test.zr @@ -1,8 +1,4 @@ func run_test[x: String] : I64 - // requires stdin - if strcmp(x, "guess_number.zr") == 0 - return 0 - printf("\033[93mBuilding %s...\033[0m", x) let cmd: String = String.concat("./target/release/zern examples/", x) @@ -14,12 +10,15 @@ func run_test[x: String] : I64 free(cmd) printf(" %ldms\n", build_end_time - build_start_time) - let run_start_time: I64 = OS.time() - if system("./out") != 0 - exit(1) - let run_end_time: I64 = OS.time() + if strcmp(x, "guess_number.zr") == 0 || strcmp(x, "tcp_server.zr") == 0 + printf("\033[93mSkipping %s...\033[0m\n") + else + let run_start_time: I64 = OS.time() + if system("./out") != 0 + exit(1) + let run_end_time: I64 = OS.time() - printf("\033[93mRunning %s...\033[0m %ldms\n", x, run_end_time - run_start_time) + printf("\033[93mRunning %s...\033[0m %ldms\n", x, run_end_time - run_start_time) func main[] : I64 system("cargo build --release")