diff --git a/examples/brainfuck.zr b/examples/brainfuck.zr index 03a1f00..8fdfb35 100644 --- a/examples/brainfuck.zr +++ b/examples/brainfuck.zr @@ -4,7 +4,8 @@ func main[] : I64 let src_len: I64 = str.len(src) let i: I64 = 0 - let memory: Ptr = c.calloc(1, 30000) + let memory: Ptr = mem.alloc(30000) + mem.zero(memory, 30000) let p: I64 = 0 while i < src_len diff --git a/examples/curl.zr b/examples/curl.zr index e361fdb..5dff0a1 100644 --- a/examples/curl.zr +++ b/examples/curl.zr @@ -4,7 +4,10 @@ func main[argc: I64, argv: Ptr] : I64 let url: String = mem.read64(argv + 8) - if c.strncmp(url, "http://", 7) != 0 + if str.len(url) <= 7 + dbg.panic("missing url scheme") + + if !str.equal(str.substr(url, 0, 7), "http://") dbg.panic("invalid url scheme") let url_len: I64 = str.len(url) diff --git a/examples/quicksort.zr b/examples/quicksort.zr index 6b899a8..94ab2fd 100644 --- a/examples/quicksort.zr +++ b/examples/quicksort.zr @@ -1,26 +1,3 @@ -func quicksort[arr: Array] : Void - do_quicksort(arr, 0, array.size(arr)-1) - -func do_quicksort[arr: Array, low: I64, high: I64] : Void - 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 = arr[high] - let i: I64 = low - 1 - for j in (low)..high - if arr[j] <= pivot - i = i + 1 - let temp: I64 = arr[i] - array.set(arr, i, arr[j]) - array.set(arr, j, temp) - let temp: I64 = arr[i + 1] - array.set(arr, i + 1, arr[high]) - array.set(arr, high, temp) - return i + 1 - func main[] : I64 let arr: Array = [] for i in 0..10 @@ -30,7 +7,7 @@ func main[] : I64 io.print_i64(arr[i]) io.print("------------") - quicksort(arr) + alg.quicksort(arr) for i in 0..array.size(arr) io.print_i64(arr[i]) diff --git a/src/codegen_x86_64.rs b/src/codegen_x86_64.rs index 57249ec..2a66c46 100644 --- a/src/codegen_x86_64.rs +++ b/src/codegen_x86_64.rs @@ -106,7 +106,7 @@ section .text ); // take that rustfmt - for name in "malloc,calloc,realloc,free,puts,putchar,printf,sprintf,snprintf,strtol,strlen,strcmp,strncmp,strcat,strcpy,strdup,strncpy,syscall,fopen,fseek,ftell,fread,fwrite,fclose,rewind,system,opendir,readdir,closedir,exit,gettimeofday,connect,socket,send,write,read,close,bind,listen,accept,getchar,gethostbyname,dlopen,dlsym,dlerror".split(",") + for name in "malloc,memset,realloc,free,puts,putchar,printf,snprintf,strtol,strlen,strcmp,strcat,strcpy,strncpy,fopen,fseek,ftell,fread,fwrite,fclose,rewind,system,opendir,readdir,closedir,exit,gettimeofday,connect,socket,send,write,read,close,bind,listen,accept,getchar,gethostbyname,dlopen,dlsym".split(",") { emit!(&mut self.output, "extern {}", name); emit!(&mut self.output, "c.{} equ {}", name, name); @@ -316,10 +316,10 @@ _builtin_set64: TokenType::Xor => { emit!(&mut self.output, " xor rax, rbx"); } - TokenType::And => { + TokenType::BitAnd => { emit!(&mut self.output, " and rax, rbx"); } - TokenType::Or => { + TokenType::BitOr => { emit!(&mut self.output, " or rax, rbx"); } TokenType::DoubleEqual => { diff --git a/src/parser.rs b/src/parser.rs index 9a82c5e..26089a1 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -115,7 +115,6 @@ impl Parser { } } - // TOOD: parse return type fn func_declaration(&mut self) -> Result { let name = self.consume(TokenType::Identifier, "expected function name")?; self.consume(TokenType::LeftBracket, "expected '[' after function name")?; @@ -304,7 +303,7 @@ impl Parser { fn logical_or(&mut self) -> Result { let mut expr = self.logical_and()?; - while self.match_token(&[TokenType::Or]) { + while self.match_token(&[TokenType::BitOr]) { let op = self.previous().clone(); let right = self.logical_and()?; expr = Expr::Binary { @@ -320,7 +319,7 @@ impl Parser { fn logical_and(&mut self) -> Result { let mut expr = self.equality()?; - while self.match_token(&[TokenType::And]) { + while self.match_token(&[TokenType::BitAnd]) { let op = self.previous().clone(); let right = self.equality()?; expr = Expr::Binary { diff --git a/src/std.zr b/src/std.zr index a3fa293..f8928ce 100644 --- a/src/std.zr +++ b/src/std.zr @@ -8,12 +8,21 @@ func mem.alloc[x: I64] : Ptr func mem.free[x: Ptr] : Void c.free(x) +func mem.zero[x: I64, size: I64] : Void + c.memset(x, 0, size) + func mem.read8[x: Ptr] : U8 return _builtin_read8(x) func mem.read64[x: Ptr] : I64 return _builtin_read64(x) +func mem.write8[x: Ptr, d: U8] : Void + _builtin_set8(x, d) + +func mem.write64[x: Ptr, d: I64] : Void + _builtin_set64(x, d) + func io.print[x: String] : Void c.puts(x) @@ -22,7 +31,9 @@ func io.print_i64[x: I64] : Void func io.read_stdin[]: String let buffer: String = mem.alloc(1025) - let n: I64 = c.syscall(0, 0, buffer, 1024) + let n: I64 = c.read(0, buffer, 1024) + if n < 0 + return "" str.set(buffer, n, 0) return buffer @@ -57,8 +68,15 @@ func str.len[s: String] : I64 func str.nth[s: String, n: I64] : U8 return mem.read8(s + n) +func str.copy[s: String] : String + let size: I64 = str.len(s) + 1 + let dup: String = mem.alloc(size) + for i in 0..size+1 + str.set(dup, i, str.nth(s, i)) + return dup + func str.set[s: String, n: I64, c: U8] : Void - _builtin_set8(s+n, c) + mem.write8(s+n, c) func str.equal[a: String, b: String] : Bool return c.strcmp(a, b) == 0 @@ -143,7 +161,7 @@ func str.reverse[s: String] : String func str.from_i64[n: I64] : String let x: String = mem.alloc(21) - c.sprintf(x, "%ld", n) + c.snprintf(x, 21, "%ld", n) return x func str.parse_i64[s: String] : I64 @@ -257,7 +275,9 @@ func math.urandom[]: I64 return n func array.new[] : Array - return c.calloc(1, 24) + let arr: Ptr = mem.alloc(24) + mem.zero(arr, 24) + return arr func array.nth[xs: Array, n: I64] : I64 // this probably should be implemented in the codegen @@ -267,7 +287,7 @@ func array.nth[xs: Array, n: I64] : I64 func array.set[xs: Array, n: I64, x: I64] : Void let data: Ptr = mem.read64(xs) - _builtin_set64(data+n*8, x) + mem.write64(data+n*8, x) func array.push[xs: Array, x: I64] : Void let data: Ptr = mem.read64(xs) @@ -279,20 +299,48 @@ func array.push[xs: Array, x: I64] : Void if capacity != 0 new_capacity = capacity * 2 let new_data: Ptr = c.realloc(data, new_capacity * 8) - _builtin_set64(xs, new_data) - _builtin_set64(xs+8, new_capacity) + mem.write64(xs, new_data) + mem.write64(xs+8, new_capacity) data = new_data - _builtin_set64(data+size*8, x) - _builtin_set64(xs+16, size + 1) + mem.write64(data+size*8, x) + mem.write64(xs+16, size + 1) func array.size[xs: Array] : I64 return mem.read64(xs+16) func array.free[xs: Array] : Void - mem.free(mem.read64(xs)) + let data: Ptr = mem.read64(xs) + if data != 0 + mem.free(data) mem.free(xs) +func alg.quicksort[arr: Array] : Void + alg._do_quicksort(arr, 0, array.size(arr)-1) + +func alg._do_quicksort[arr: Array, low: I64, high: I64] : Void + if low < high + let i: I64 = alg._partition(arr, low, high) + alg._do_quicksort(arr, low, i - 1) + alg._do_quicksort(arr, i + 1, high) + +func alg._partition[arr: Array, low: I64, high: I64] : I64 + let pivot: I64 = arr[high] + let i: I64 = low - 1 + for j in (low)..high + if arr[j] <= pivot + i = i + 1 + let temp: I64 = arr[i] + array.set(arr, i, arr[j]) + array.set(arr, j, temp) + let temp: I64 = arr[i + 1] + array.set(arr, i + 1, arr[high]) + array.set(arr, high, temp) + return i + 1 + +func os.exit[code: I64] : Void + c.exit(code) + func os.time[] : I64 let tv: Ptr = mem.alloc(16) c.gettimeofday(tv, 0) @@ -319,7 +367,7 @@ func os.listdir[path: String] : Array skip = true if !skip - array.push(files, c.strdup(entry + 19)) + array.push(files, str.copy(entry + 19)) c.closedir(dir) return files @@ -328,11 +376,12 @@ func net.listen[port: I64] : I64 if s < 0 return -1 - let sa: Ptr = c.calloc(1, 16) - str.set(sa, 0, 2) - str.set(sa, 1, 0) - str.set(sa, 2, (port >> 8) & 255) - str.set(sa, 3, port & 255) + let sa: Ptr = mem.alloc(16) + mem.zero(sa, 16) + mem.write8(sa + 0, 2) + mem.write8(sa + 1, 0) + mem.write8(sa + 2, (port >> 8) & 255) + mem.write8(sa + 3, port & 255) if c.bind(s, sa, 16) < 0 c.close(s) @@ -356,14 +405,15 @@ func net.connect[host: String, port: I64] : I64 if s < 0 return -1 - let sa: Ptr = c.calloc(1, 16) - str.set(sa, 0, 2) - str.set(sa, 2, (port >> 8) & 255) - str.set(sa, 3, port & 255) - str.set(sa, 4, mem.read8(ip_ptr + 0)) - str.set(sa, 5, mem.read8(ip_ptr + 1)) - str.set(sa, 6, mem.read8(ip_ptr + 2)) - str.set(sa, 7, mem.read8(ip_ptr + 3)) + let sa: Ptr = mem.alloc(16) + mem.zero(sa, 16) + mem.write8(sa + 0, 2) + mem.write8(sa + 2, (port >> 8) & 255) + mem.write8(sa + 3, port & 255) + mem.write8(sa + 4, mem.read8(ip_ptr + 0)) + mem.write8(sa + 5, mem.read8(ip_ptr + 1)) + mem.write8(sa + 6, mem.read8(ip_ptr + 2)) + mem.write8(sa + 7, mem.read8(ip_ptr + 3)) if c.connect(s, sa, 16) < 0 mem.free(sa) diff --git a/src/tokenizer.rs b/src/tokenizer.rs index 50bec4d..7224f0f 100644 --- a/src/tokenizer.rs +++ b/src/tokenizer.rs @@ -15,8 +15,8 @@ pub enum TokenType { Xor, Bang, Colon, - And, - Or, + BitAnd, + BitOr, Pipe, DoubleDot, ShiftLeft, @@ -168,12 +168,12 @@ impl Tokenizer { self.add_token(TokenType::Slash) } } - '&' => self.add_token(TokenType::And), + '&' => self.add_token(TokenType::BitAnd), '|' => { if self.match_char('>') { self.add_token(TokenType::Pipe); } else { - self.add_token(TokenType::Or); + self.add_token(TokenType::BitOr); } } '!' => { diff --git a/test.zr b/test.zr index 7892957..55e051c 100644 --- a/test.zr +++ b/test.zr @@ -4,22 +4,22 @@ func run_test[x: String] : Void let build_start_time: I64 = os.time() if c.system(cmd) != 0 - c.exit(1) + os.exit(1) let build_end_time: I64 = os.time() mem.free(cmd) c.printf(" %ldms\n", build_end_time - build_start_time) - if str.equal(x, "guess_number.zr") | str.equal(x, "tcp_server.zr") + if str.equal(x, "guess_number.zr") | str.equal(x, "tcp_server.zr") | str.equal(x, "raylib.zr") c.printf("\033[93mSkipping %s...\033[0m\n", x) else let run_start_time: I64 = os.time() if str.equal(x, "curl.zr") if c.system("./out http://example.com") != 0 - c.exit(1) + os.exit(1) else if c.system("./out") != 0 - c.exit(1) + os.exit(1) let run_end_time: I64 = os.time() c.printf("\033[93mRunning %s...\033[0m %ldms\n", x, run_end_time - run_start_time)