diff --git a/README.md b/README.md index 0dec895..daf6d44 100644 --- a/README.md +++ b/README.md @@ -5,13 +5,15 @@ A very cool language ## Features * Clean indentation-based syntax * Compiles to x86_64 Assembly +* ~~No libc required~~ (SOON; still used for `malloc,realloc,free,snprintf,system,gethostbyname`) +* Produces tiny static executables (~50KB with musl) * Sometimes works * Has the pipe operator ## Syntax ```rust func main[] : I64 - let answer: I64 = math.abs(math.urandom()) % 100 + let answer: I64 = math.abs(os.urandom()) % 100 while true io.println("Guess a number: ") diff --git a/examples/brainfuck.zr b/examples/brainfuck.zr index 042bc72..5537f95 100644 --- a/examples/brainfuck.zr +++ b/examples/brainfuck.zr @@ -22,7 +22,7 @@ func main[] : I64 else if op == '.' io.print_char(memory[p]) else if op == ',' - str.set(memory, p, c.getchar()) + str.set(memory, p, io.read_char()) else if op == '[' if !memory[p] i = i + 1 diff --git a/examples/curl.zr b/examples/curl.zr index 8e9f51b..667ff73 100644 --- a/examples/curl.zr +++ b/examples/curl.zr @@ -27,9 +27,13 @@ func main[argc: I64, argv: Ptr] : I64 if s < 0 dbg.panic("failed to connect") - 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, str.len(req), 0) + // very leaky + let req: String = "GET " + req = str.concat(req, path) + req = str.concat(req, " HTTP/1.0\r\nHost: ") + req = str.concat(req, host) + req = str.concat(req, "\r\nConnection: close\r\n\r\n") + net.send(s, req, str.len(req)) mem.free(req) let header_buf: String = mem.alloc(8192) @@ -38,7 +42,7 @@ func main[argc: I64, argv: Ptr] : I64 let end_index: I64 = -1 while !found & header_size < 8192 - let n: I64 = c.read(s, header_buf + header_size, 8192 - header_size) + let n: I64 = net.read(s, header_buf + header_size, 8192 - header_size) if n <= 0 break let current_size: I64 = header_size + n @@ -52,15 +56,15 @@ func main[argc: I64, argv: Ptr] : I64 header_size = current_size if end_index < header_size - c.write(1, header_buf + end_index, header_size - end_index) + io.print_sized(header_buf + end_index, header_size - end_index) mem.free(header_buf) let buffer: Ptr = mem.alloc(4096) while true - let n: I64 = c.read(s, buffer, 4096) + let n: I64 = net.read(s, buffer, 4096) if n <= 0 break - c.write(1, buffer, n) + io.print_sized(buffer, n) mem.free(buffer) - c.close(s) \ No newline at end of file + net.close(s) \ No newline at end of file diff --git a/examples/guess_number.zr b/examples/guess_number.zr index cb41ac5..bfbf03f 100644 --- a/examples/guess_number.zr +++ b/examples/guess_number.zr @@ -1,5 +1,5 @@ func main[] : I64 - let answer: I64 = math.abs(math.urandom()) % 100 + let answer: I64 = math.abs(os.urandom()) % 100 while true io.println("Guess a number: ") diff --git a/examples/quicksort.zr b/examples/quicksort.zr index afad6f2..eb43163 100644 --- a/examples/quicksort.zr +++ b/examples/quicksort.zr @@ -1,7 +1,7 @@ func main[] : I64 let arr: Array = [] for i in 0..10 - array.push(arr, math.abs(math.urandom() % 1000)) + array.push(arr, math.abs(os.urandom() % 1000)) for i in 0..array.size(arr) io.println_i64(array.nth(arr, i)) diff --git a/examples/tcp_server.zr b/examples/tcp_server.zr index dbc2209..4a04bb8 100644 --- a/examples/tcp_server.zr +++ b/examples/tcp_server.zr @@ -3,10 +3,10 @@ func main[] : I64 let resp: String = mem.alloc(60000) while true - let conn: I64 = c.accept(s, 0, 0) + let conn: I64 = net.accept(s) if conn < 0 continue - let n: I64 = c.read(conn, resp, 60000) - c.send(conn, resp, n, 0) - c.close(conn) \ No newline at end of file + let n: I64 = net.read(conn, resp, 60000) + net.send(conn, resp, n) + net.close(conn) \ No newline at end of file diff --git a/src/codegen_x86_64.rs b/src/codegen_x86_64.rs index 68aa3b8..ed9f17f 100644 --- a/src/codegen_x86_64.rs +++ b/src/codegen_x86_64.rs @@ -106,8 +106,7 @@ section .text ); // take that rustfmt - for name in "malloc,realloc,free,snprintf,system,gettimeofday,send,write,read,close,getchar,gethostbyname".split(",") - { + for name in "malloc,realloc,free,snprintf,system,gethostbyname".split(",") { emit!(&mut self.output, "extern {}", name); emit!(&mut self.output, "c.{} equ {}", name, name); } diff --git a/src/std.zr b/src/std.zr index 52461f8..d5e75e7 100644 --- a/src/std.zr +++ b/src/std.zr @@ -38,6 +38,9 @@ func io.println[x: String] : Void io.print(x) io.print("\n") +func io.print_sized[x: String, size: I64] : Void + _builtin_syscall(1, 1, x, size) + func io.print_char[x: U8] : Void let s: String = mem.alloc(1) str.set(s, 0, x) @@ -54,6 +57,14 @@ func io.println_i64[x: I64] : Void io.println(s) mem.free(s) +func io.read_char[] : U8 + let s: String = mem.alloc(1) + str.set(s, 0, 0) + _builtin_syscall(0, 0, s, 1) + let c: U8 = s[0] + mem.free(s) + return c + func io.read_stdin[]: String let buffer: String = mem.alloc(1025) let n: I64 = _builtin_syscall(0, 0, buffer, 1024) @@ -313,15 +324,6 @@ func math.is_prime[n: I64]: Bool i = i + 6 return true -func math.urandom[]: I64 - let buffer: Ptr = mem.alloc(8) - let fd: I64 = _builtin_syscall(2, "/dev/urandom", 0, 0) // open - _builtin_syscall(0, fd, buffer, 8) // read - _builtin_syscall(3, fd) // close - let n: I64 = mem.read64(buffer) - mem.free(buffer) - return n - func array.new[] : Array let arr: Ptr = mem.alloc(24) mem.zero(arr, 24) @@ -390,11 +392,20 @@ func alg._partition[arr: Array, low: I64, high: I64] : I64 func os.exit[code: I64] : Void _builtin_syscall(60, code) +func os.urandom[]: I64 + let buffer: Ptr = mem.alloc(8) + let fd: I64 = _builtin_syscall(2, "/dev/urandom", 0, 0) // open + _builtin_syscall(0, fd, buffer, 8) // read + _builtin_syscall(3, fd) // close + let n: I64 = mem.read64(buffer) + mem.free(buffer) + return n + func os.time[] : I64 let tv: Ptr = mem.alloc(16) - c.gettimeofday(tv, 0) + _builtin_syscall(96, tv, 0) // gettimeofday let seconds: I64 = mem.read64(tv) - let microseconds: I64 = mem.read64(tv+8) + let microseconds: I64 = mem.read64(tv + 8) mem.free(tv) return seconds * 1000 + microseconds / 1000 @@ -481,4 +492,16 @@ func net.connect[host: String, port: I64] : I64 return -1 mem.free(sa) - return s \ No newline at end of file + return s + +func net.accept[s: I64] : I64 + return _builtin_syscall(43, s, 0, 0) + +func net.send[s: I64, data: String, size: I64] : Void + _builtin_syscall(44, s, data, size, 0, 0, 0) + +func net.read[s: I64, buffer: Ptr, size: I64] : I64 + return _builtin_syscall(0, s, buffer, size) + +func net.close[s: I64] : Void + _builtin_syscall(3, s) \ No newline at end of file