From 3fd62c608311547cfbf43934a2a731b0ec116525 Mon Sep 17 00:00:00 2001 From: Toni Date: Sun, 3 Aug 2025 10:37:18 +0200 Subject: [PATCH] some std wrappers around libc --- examples/brainfuck.zr | 4 +- examples/curl.zr | 16 +++---- examples/euler4.zr | 6 +-- examples/euler8.zr | 2 +- examples/tcp_server.zr | 12 ++--- src/codegen_x86_64.rs | 6 +-- src/std.zr | 105 +++++++++++++++++++++++++++++------------ test.zr | 6 +-- 8 files changed, 101 insertions(+), 56 deletions(-) diff --git a/examples/brainfuck.zr b/examples/brainfuck.zr index e3d80e7..f1175e2 100644 --- a/examples/brainfuck.zr +++ b/examples/brainfuck.zr @@ -1,7 +1,7 @@ func main[] : I64 // https://brainfuck.org/sierpinski.b let src: String = "++++++++[>+>++++<<-]>++>>+<[-[>>+<<-]+>>]>+[-<<<[->[+[-]+>++>>>-<<]<[<]>>++++++[<<+++++>>-]+<<++.[-]<<]>.>+[>>]>+]" - let src_len: I64 = c.strlen(src) + let src_len: I64 = str.len(src) let i: I64 = 0 let memory: Ptr = c.calloc(1, 30000) @@ -45,4 +45,4 @@ func main[] : I64 i = i + 1 - c.free(memory) \ No newline at end of file + mem.free(memory) \ No newline at end of file diff --git a/examples/curl.zr b/examples/curl.zr index 9629d6b..280fe9d 100644 --- a/examples/curl.zr +++ b/examples/curl.zr @@ -7,7 +7,7 @@ func main[argc: I64, argv: Ptr] : I64 if c.strncmp(url, "http://", 7) != 0 dbg.panic("invalid url scheme") - let url_len: I64 = c.strlen(url) + let url_len: I64 = str.len(url) let host_start: I64 = 7 let i: I64 = host_start while i < url_len @@ -24,12 +24,12 @@ func main[argc: I64, argv: Ptr] : I64 if s < 0 dbg.panic("failed to connect") - let req: String = c.malloc(2048) + let req: String = mem.alloc(2048) c.snprintf(req, 2048, "GET %s HTTP/1.0\r\nHost: %s\r\nConnection: close\r\n\r\n", path, host) - c.send(s, req, c.strlen(req), 0) - c.free(req) + c.send(s, req, str.len(req), 0) + mem.free(req) - let header_buf: Ptr = c.malloc(8192) + let header_buf: Ptr = mem.alloc(8192) let header_size: I64 = 0 let found: Bool = false let end_index: I64 = -1 @@ -51,14 +51,14 @@ func main[argc: I64, argv: Ptr] : I64 if end_index < header_size c.write(1, header_buf + end_index, header_size - end_index) - c.free(header_buf) + mem.free(header_buf) - let buffer: Ptr = c.malloc(4096) + let buffer: Ptr = mem.alloc(4096) while true let n: I64 = c.read(s, buffer, 4096) if n <= 0 break c.write(1, buffer, n) - c.free(buffer) + mem.free(buffer) c.close(s) \ No newline at end of file diff --git a/examples/euler4.zr b/examples/euler4.zr index 8dc3a2a..fa00314 100644 --- a/examples/euler4.zr +++ b/examples/euler4.zr @@ -6,8 +6,8 @@ func main[] : I64 if a * b > out let s: String = str.from_i64(a * b) let s_rev: String = str.reverse(s) - if c.strcmp(s, s_rev) == 0 + if str.equal(s, s_rev) out = a * b - c.free(s) - c.free(s_rev) + mem.free(s) + mem.free(s_rev) io.print_i64(out) \ No newline at end of file diff --git a/examples/euler8.zr b/examples/euler8.zr index db8adbc..7761881 100644 --- a/examples/euler8.zr +++ b/examples/euler8.zr @@ -2,7 +2,7 @@ func main[] : I64 let n: String = "7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450" let out: I64 = 0 - let max: I64 = c.strlen(n) - 13 + let max: I64 = str.len(n) - 13 for i in 0..max let s: I64 = 1 let j: I64 = 0 diff --git a/examples/tcp_server.zr b/examples/tcp_server.zr index 7ff8a48..dbc2209 100644 --- a/examples/tcp_server.zr +++ b/examples/tcp_server.zr @@ -1,12 +1,12 @@ func main[] : I64 let s: I64 = net.listen(8000) - let resp: String = c.malloc(60000) + let resp: String = mem.alloc(60000) while true - let c: I64 = c.accept(s, 0, 0) - if c < 0 + let conn: I64 = c.accept(s, 0, 0) + if conn < 0 continue - let n: I64 = c.read(c, resp, 60000) - c.send(c, resp, n, 0) - c.close(c) \ No newline at end of file + let n: I64 = c.read(conn, resp, 60000) + c.send(conn, resp, n, 0) + c.close(conn) \ No newline at end of file diff --git a/src/codegen_x86_64.rs b/src/codegen_x86_64.rs index c6a028b..7f6b7cd 100644 --- a/src/codegen_x86_64.rs +++ b/src/codegen_x86_64.rs @@ -225,10 +225,8 @@ _builtin_set64: self.compile_stmt(env, *body)?; - if name.lexeme == "main" { - emit!(&mut self.output, " mov rax, 0"); - } - + // fallback to returning null + emit!(&mut self.output, " mov rax, 0"); emit!(&mut self.output, " mov rsp, rbp"); emit!(&mut self.output, " pop rbp"); emit!(&mut self.output, " ret"); diff --git a/src/std.zr b/src/std.zr index bd90cb0..56eaec7 100644 --- a/src/std.zr +++ b/src/std.zr @@ -2,6 +2,12 @@ func dbg.panic[msg: String] : Void c.printf("PANIC: %s\n", msg) c.exit(1) +func mem.alloc[x: I64] : Ptr + return c.malloc(x) + +func mem.free[x: I64] : Ptr + return c.free(x) + func mem.deref8[x: Ptr] : I64 return _builtin_deref8(x) @@ -15,7 +21,7 @@ func io.print_i64[x: I64] : Void c.printf("%ld\n", x) func io.read_stdin[]: String - let buffer: String = c.malloc(1025) + let buffer: String = mem.alloc(1025) let n: I64 = c.syscall(0, 0, buffer, 1024) str.set(buffer, n, 0) return buffer @@ -29,7 +35,7 @@ func io.read_file[path: String]: String let size: I64 = c.ftell(file) c.rewind(file) - let buffer: String = c.malloc(size + 1) + let buffer: String = mem.alloc(size + 1) let n: I64 = c.fread(buffer, 1, size, file) str.set(buffer, n, 0) @@ -41,43 +47,49 @@ func io.write_file[path: String, content: String] : Void if !file dbg.panic("failed to open file") - c.fwrite(content, 1, c.strlen(content), file) + c.fwrite(content, 1, str.len(content), file) c.fclose(file) +func str.len[s: String] : I64 + return c.strlen(s) + func str.nth[s: String, n: I64] : U8 return mem.deref8(s + n) func str.set[s: String, n: I64, c: U8] : Void _builtin_set8(s+n, c) -func str.is_whitespace[c: U8] : Bool - return c == ' ' | c == 10 | c == 13 | c == 9 +func str.equal[a: String, b: String] : Bool + return c.strcmp(a, b) == 0 + +func str.is_whitespace[x: U8] : Bool + return x == ' ' | x == 10 | x == 13 | x == 9 func str.concat[a: String, b: String] : String - let c: String = c.malloc(c.strlen(a) + c.strlen(b) + 1) - c.strcpy(c, a) - c.strcat(c, b) - return c + let out: String = mem.alloc(str.len(a) + str.len(b) + 1) + c.strcpy(out, a) + c.strcat(out, b) + return out func str.find[s: String, c: U8] : I64 - let s_len: I64 = c.strlen(s) + let s_len: I64 = str.len(s) for i in 0..s_len if str.nth(s, i) == c return i return -1 func str.substr[s: String, start: I64, length: I64] : String - if start < 0 | length < 0 | start + length > c.strlen(s) + if start < 0 | length < 0 | start + length > str.len(s) dbg.panic("String.substr out of bounds") - let out: String = c.malloc(length + 1) + let out: String = mem.alloc(length + 1) c.strncpy(out, s + start, length) str.set(out, length, 0) return out func str.trim[s: String] : String let start: I64 = 0 - let end: I64 = c.strlen(s) - 1 + let end: I64 = str.len(s) - 1 while start <= end & str.is_whitespace(str.nth(s, start)) start = start + 1 @@ -87,9 +99,41 @@ func str.trim[s: String] : String return str.substr(s, start, end - start + 1) +func str.split[haystack: String, needle: String]: Array + let haystack_len: I64 = str.len(haystack) + let needle_len: I64 = str.len(needle) + let result: Array = [] + + if !needle_len + if !haystack_len + return result + else + for i in 0..haystack_len + array.push(result, str.substr(haystack, i, 1)) + return result + + let start: I64 = 0 + let i: I64 = 0 + while i < haystack_len + if i <= haystack_len - needle_len + let match: Bool = true + for j in 0..needle_len + if str.nth(haystack, i+j) != str.nth(needle, j) + match = false + break + if match + array.push(result, str.substr(haystack, start, i - start)) + start = i + needle_len + i = i + needle_len + continue + i = i + 1 + + array.push(result, str.substr(haystack, start, haystack_len - start)) + return result + func str.reverse[s: String] : String - let len: I64 = c.strlen(s) - let out: String = c.malloc(len + 1) + let len: I64 = str.len(s) + let out: String = mem.alloc(len + 1) for i in 0..len str.set(out, i, str.nth(s, len - i - 1)) @@ -97,7 +141,7 @@ func str.reverse[s: String] : String return out func str.from_i64[n: I64] : String - let x: String = c.malloc(21) + let x: String = mem.alloc(21) c.sprintf(x, "%ld", n) return x @@ -106,9 +150,9 @@ func str.parse_i64[s: String] : I64 func str.hex_encode[s: String] : String let hex_chars: String = "0123456789abcdef" - let s_len: I64 = c.strlen(s) + let s_len: I64 = str.len(s) let j: I64 = 0 - let out: String = c.malloc(s_len*2+1) + let out: String = mem.alloc(s_len*2+1) for i in 0..s_len let high: U8 = (str.nth(s, i) >> 4) & 15 @@ -128,10 +172,10 @@ func str.from_hex_digit[d: U8] : I64 return d - '0' func str.hex_decode[s: String] : String - let s_len: I64 = c.strlen(s) + let s_len: I64 = str.len(s) let i: I64 = 0 let j: I64 = 0 - let out: String = c.malloc(s_len/2+1) + let out: String = mem.alloc(s_len/2+1) while i < s_len str.set(out, j, str.from_hex_digit(str.nth(s, i)) * 16 + str.from_hex_digit(str.nth(s, i+1))) @@ -203,17 +247,20 @@ func math.is_prime[n: I64]: Bool return true func math.urandom[]: I64 - let buffer: Ptr = c.malloc(8) + let buffer: Ptr = mem.alloc(8) let file: Ptr = c.fopen("/dev/urandom", "rb") c.fread(buffer, 8, 1, file) c.fclose(file) let n: I64 = mem.deref64(buffer) - c.free(buffer) + mem.free(buffer) return n func array.new[] : Array return c.calloc(1, 24) +func array.nth[xs: Array, n: I64] : I64 + return xs[n] + func array.set[xs: Array, n: I64, x: I64] : Void let data: Ptr = mem.deref64(xs) _builtin_set64(data+n*8, x) @@ -239,15 +286,15 @@ func array.size[xs: Array] : I64 return mem.deref64(xs+16) func array.free[xs: Array] : Void - c.free(mem.deref64(xs)) - c.free(xs) + mem.free(mem.deref64(xs)) + mem.free(xs) func os.time[] : I64 - let tv: Ptr = c.malloc(16) + let tv: Ptr = mem.alloc(16) c.gettimeofday(tv, 0) let seconds: I64 = mem.deref64(tv) let microseconds: I64 = mem.deref64(tv+8) - c.free(tv) + mem.free(tv) return seconds * 1000 + microseconds / 1000 func os.listdir[path: String] : Array @@ -286,7 +333,7 @@ func net.listen[port: I64] : I64 if c.bind(s, sa, 16) < 0 c.close(s) return -1 - c.free(sa) + mem.free(sa) if c.listen(s, 1) < 0 c.close(s) @@ -315,9 +362,9 @@ func net.connect[host: String, port: I64] : I64 str.set(sa, 7, mem.deref8(ip_ptr + 3)) if c.connect(s, sa, 16) < 0 - c.free(sa) + mem.free(sa) c.close(s) return -1 - c.free(sa) + mem.free(sa) return s \ No newline at end of file diff --git a/test.zr b/test.zr index 7d10e39..f071851 100644 --- a/test.zr +++ b/test.zr @@ -7,14 +7,14 @@ func run_test[x: String] : Void c.exit(1) let build_end_time: I64 = os.time() - c.free(cmd) + mem.free(cmd) c.printf(" %ldms\n", build_end_time - build_start_time) - if c.strcmp(x, "guess_number.zr") == 0 | c.strcmp(x, "tcp_server.zr") == 0 + if str.equal(x, "guess_number.zr") | str.equal(x, "tcp_server.zr") c.printf("\033[93mSkipping %s...\033[0m\n", x) else let run_start_time: I64 = os.time() - if c.strcmp(x, "curl.zr") == 0 + if str.equal(x, "curl.zr") if c.system("./out http://devernay.free.fr/hacks/chip8/C8TECH10.HTM") != 0 c.exit(1) else