diff --git a/examples/chip8.zr b/examples/chip8.zr index 0677b8e..871a732 100644 --- a/examples/chip8.zr +++ b/examples/chip8.zr @@ -290,7 +290,9 @@ func main[argc: i64, argv: ptr] : i64 c := chip8_create() - buffer : Blob = must(io.read_binary_file?(path)) + ~buffer, ok := io.read_binary_file(path) + if !ok + panic("failed to read file") for i in 0..buffer->size c->memory[0x200 + i] = buffer->data[i] diff --git a/examples/curl.zr b/examples/curl.zr index 878d4c5..9a3e2e6 100644 --- a/examples/curl.zr +++ b/examples/curl.zr @@ -26,9 +26,13 @@ func main[argc: i64, argv: ptr] : i64 if i < url_len path = str.substr(url, i, url_len - i) - addr : i64 = must(net.resolve?(host)) + ~addr, ok := net.resolve(host) + if !ok + panic("failed to resolve host") - s : i64 = must(net.connect?(addr, 80)) + ~s, ok := net.connect(addr, 80) + if !ok + panic("failed to connect") // TODO: add string builder to std req := "GET " diff --git a/examples/puzzles/aoc2024_01.zr b/examples/puzzles/aoc2024_01.zr index 5bcb54f..0fc3966 100644 --- a/examples/puzzles/aoc2024_01.zr +++ b/examples/puzzles/aoc2024_01.zr @@ -15,7 +15,11 @@ func part2[l1: Array, l2: Array] : void io.println_i64(out) func main[] : i64 - lines : Array = must(io.read_text_file?("input.txt")) |> str.split("\n") + ~input, ok := io.read_text_file("input.txt") + if !ok + panic("failed to open input.txt") + + lines := str.split(input, "\n") l1 := [] l2 := [] diff --git a/examples/puzzles/aoc2024_02.zr b/examples/puzzles/aoc2024_02.zr index 88a8e3c..c1b96d7 100644 --- a/examples/puzzles/aoc2024_02.zr +++ b/examples/puzzles/aoc2024_02.zr @@ -40,7 +40,11 @@ func part2[data: Array] : void io.println_i64(out) func main[] : i64 - lines := must(io.read_text_file?("input.txt")) |> str.split("\n") + ~input, ok := io.read_text_file("input.txt") + if !ok + panic("failed to open input.txt") + + lines := str.split(input, "\n") data := [] for i in 0..lines->size diff --git a/examples/puzzles/aoc2024_04.zr b/examples/puzzles/aoc2024_04.zr index bc2c9ef..4d5fbea 100644 --- a/examples/puzzles/aoc2024_04.zr +++ b/examples/puzzles/aoc2024_04.zr @@ -56,7 +56,11 @@ func part2[lines: Array] : void io.println_i64(out) func main[] : i64 - lines : Array = must(io.read_text_file?("input.txt")) |> str.split("\n") + ~input, ok := io.read_text_file("input.txt") + if !ok + panic("failed to open input.txt") + + lines := str.split(input, "\n") part1(lines) part2(lines) diff --git a/examples/puzzles/aoc2024_05.zr b/examples/puzzles/aoc2024_05.zr index 9d0b167..cf02440 100644 --- a/examples/puzzles/aoc2024_05.zr +++ b/examples/puzzles/aoc2024_05.zr @@ -47,7 +47,11 @@ func part2[updates: Array, rules_left: Array, rules_right: Array] : void io.println_i64(out) func main[] : i64 - data := must(io.read_text_file?("input.txt")) |> str.split("\n\n") + ~input, ok := io.read_text_file("input.txt") + if !ok + panic("failed to open input.txt") + + data := str.split(input, "\n\n") rules_left := [] rules_right := [] diff --git a/examples/puzzles/aoc2024_07.zr b/examples/puzzles/aoc2024_07.zr index 1cbf497..ca7ee90 100644 --- a/examples/puzzles/aoc2024_07.zr +++ b/examples/puzzles/aoc2024_07.zr @@ -61,7 +61,11 @@ func part2[equations: Array] : void io.println_i64(out) func main[] : i64 - lines := must(io.read_text_file?("input.txt")) |> str.split("\n") + ~input, ok := io.read_text_file("input.txt") + if !ok + panic("failed to open input.txt") + + lines := str.split(input, "\n") equations := [] for i in 0..lines->size diff --git a/examples/puzzles/aoc2025_01.zr b/examples/puzzles/aoc2025_01.zr index 1869390..28ad2b8 100644 --- a/examples/puzzles/aoc2025_01.zr +++ b/examples/puzzles/aoc2025_01.zr @@ -47,7 +47,11 @@ func part2[lines: Array] : void io.println_i64(password) func main[] : i64 - lines := must(io.read_text_file?("input.txt")) |> str.split("\n") + ~input, ok := io.read_text_file("input.txt") + if !ok + panic("failed to open input.txt") + + lines := str.split(input, "\n") part1(lines) part2(lines) diff --git a/examples/puzzles/aoc2025_02.zr b/examples/puzzles/aoc2025_02.zr index 92241cd..8c57e08 100644 --- a/examples/puzzles/aoc2025_02.zr +++ b/examples/puzzles/aoc2025_02.zr @@ -54,7 +54,11 @@ func part2[ranges: Array] : void io.println_i64(sum) func main[] : i64 - ranges := must(io.read_text_file?("input.txt")) |> str.split(",") + ~input, ok := io.read_text_file("input.txt") + if !ok + panic("failed to open input.txt") + + ranges := str.split(input, ",") part1(ranges) part2(ranges) diff --git a/examples/puzzles/aoc2025_03.zr b/examples/puzzles/aoc2025_03.zr index a3af430..e756798 100644 --- a/examples/puzzles/aoc2025_03.zr +++ b/examples/puzzles/aoc2025_03.zr @@ -45,7 +45,11 @@ func part2[lines: Array] : void io.println_i64(sum) func main[] : i64 - lines := must(io.read_text_file?("input.txt")) |> str.split("\n") + ~input, ok := io.read_text_file("input.txt") + if !ok + panic("failed to open input.txt") + + lines := str.split(input, "\n") part1(lines) part2(lines) diff --git a/examples/tcp_server.zr b/examples/tcp_server.zr index dcf1082..1c22de3 100644 --- a/examples/tcp_server.zr +++ b/examples/tcp_server.zr @@ -1,5 +1,7 @@ func main[] : i64 - s : i64 = must(net.listen?(net.pack_addr(127, 0, 0, 1), 8000)) + ~s, ok := net.listen(net.pack_addr(127, 0, 0, 1), 8000) + if !ok + panic("failed to listen") io.println("Listening on port 8000...") diff --git a/examples/udp_server.zr b/examples/udp_server.zr index ea86539..b016019 100644 --- a/examples/udp_server.zr +++ b/examples/udp_server.zr @@ -1,5 +1,7 @@ func main[] : i64 - s : net.UDPSocket = must(net.create_udp_server?(net.pack_addr(127, 0, 0, 1), 8000)) + ~s, ok := net.create_udp_server(net.pack_addr(127, 0, 0, 1), 8000) + if !ok + panic("net.create_udp_server failed") io.println("Listening on port 8000...") while true diff --git a/src/codegen_x86_64.rs b/src/codegen_x86_64.rs index 425bcb5..80bd322 100644 --- a/src/codegen_x86_64.rs +++ b/src/codegen_x86_64.rs @@ -115,8 +115,6 @@ section .bss _heap_head: resq 1 _heap_tail: resq 1 _environ: resq 1 - _err_code: resq 1 - _err_msg: resq 1 section .text._builtin_heap_head _builtin_heap_head: @@ -128,16 +126,6 @@ _builtin_heap_tail: lea rax, [rel _heap_tail] ret -section .text._builtin_err_code -_builtin_err_code: - lea rax, [rel _err_code] - ret - -section .text._builtin_err_msg -_builtin_err_msg: - lea rax, [rel _err_msg] - ret - section .text._builtin_read64 _builtin_read64: mov rax, QWORD [rdi] diff --git a/src/std/net.zr b/src/std/net.zr index 72ddccb..4aac2e3 100644 --- a/src/std/net.zr +++ b/src/std/net.zr @@ -4,18 +4,15 @@ const SOCK_DGRAM = 2 const SOL_SOCKET = 1 const SO_REUSEADDR = 2 -func net.listen?[packed_host: i64, port: i64] : i64 - err.clear() +func net.listen[packed_host: i64, port: i64] : i64, bool s := _builtin_syscall(SYS_socket, AF_INET, SOCK_STREAM, 0) if s < 0 - err.set(ERR_SYSCALL_FAILED, "net.listen?: failed to create a socket") - return -1 + return -1, false optval := 1 if _builtin_syscall(SYS_setsockopt, s, SOL_SOCKET, SO_REUSEADDR, ^optval, 8) < 0 _builtin_syscall(SYS_close, s) - err.set(ERR_SYSCALL_FAILED, "net.listen?: setsockopt() failed") - return -1 + return -1, false sa := mem.alloc(16) mem.zero(sa, 16) @@ -31,23 +28,19 @@ func net.listen?[packed_host: i64, port: i64] : i64 if _builtin_syscall(SYS_bind, s, sa, 16) < 0 _builtin_syscall(SYS_close, s) mem.free(sa) - err.set(ERR_SYSCALL_FAILED, "net.listen?: failed to bind") - return -1 + return -1, false mem.free(sa) if _builtin_syscall(SYS_listen, s, 128) < 0 _builtin_syscall(SYS_close, s) - err.set(ERR_SYSCALL_FAILED, "net.listen?: listen() failed") - return -1 + return -1, false - return s + return s, true -func net.connect?[packed_host: i64, port: i64] : i64 - err.clear() +func net.connect[packed_host: i64, port: i64] : i64, bool s := _builtin_syscall(SYS_socket, AF_INET, SOCK_STREAM, 0) if s < 0 - err.set(ERR_SYSCALL_FAILED, "net.connect?: failed to create a socket") - return -1 + return -1, false sa := mem.alloc(16) mem.zero(sa, 16) @@ -63,11 +56,10 @@ func net.connect?[packed_host: i64, port: i64] : i64 if _builtin_syscall(SYS_connect, s, sa, 16) < 0 mem.free(sa) _builtin_syscall(SYS_close, s) - err.set(ERR_CONNECTION_FAILED, "net.connect?: connection failed") - return -1 + return -1, false mem.free(sa) - return s + return s, true func net.accept[s: i64, addr: ptr] : i64 addrlen := 16 @@ -89,15 +81,13 @@ struct net.UDPSocket fd: i64 addr: ptr -func net.create_udp_client?[packed_host: i64, port: i64] : net.UDPSocket - err.clear() +func net.create_udp_client[packed_host: i64, port: i64] : net.UDPSocket, bool s := new* net.UDPSocket s->fd = _builtin_syscall(SYS_socket, AF_INET, SOCK_DGRAM, 0) if s->fd < 0 mem.free(s) - err.set(ERR_SYSCALL_FAILED, "net.create_udp_client?: failed to create a socket") - return 0 as net.UDPSocket + return 0 as net.UDPSocket, false s->addr = mem.alloc(16) mem.zero(s->addr, 16) @@ -109,20 +99,18 @@ func net.create_udp_client?[packed_host: i64, port: i64] : net.UDPSocket s->addr[5] = (packed_host >> 16) & 255 s->addr[6] = (packed_host >> 8) & 255 s->addr[7] = packed_host & 255 - return s + return s, true -func net.create_udp_server?[packed_host: i64, port: i64] : net.UDPSocket - err.clear() - s := net.create_udp_client?(packed_host, port) - if err.check() - return 0 as net.UDPSocket +func net.create_udp_server[packed_host: i64, port: i64] : net.UDPSocket, bool + ~s, ok := net.create_udp_client(packed_host, port) + if !ok + return 0 as net.UDPSocket, false if _builtin_syscall(SYS_bind, s->fd, s->addr, 16) < 0 net.UDPSocket.close_and_free(s) - err.set(ERR_SYSCALL_FAILED, "net.create_udp_server?: failed to bind") - return 0 as net.UDPSocket + return 0 as net.UDPSocket, false - return s + return s, true func net.udp_send_to[s: net.UDPSocket, addr: ptr, data: ptr, size: i64] : void _builtin_syscall(SYS_sendto, s->fd, data, size, 0, addr, 16) @@ -158,7 +146,7 @@ const DNS_RECURSION_DESIRED = 256 func net.encode_dns_name[domain: str] : Blob domain_len := str.len(domain) - buf : Blob = must(Blob.alloc?(domain_len + 2)) + buf := Blob.alloc(domain_len + 2) out_pos := 0 part_start := 0 i := 0 @@ -177,7 +165,7 @@ func net.encode_dns_name[domain: str] : Blob func net.build_dns_query[domain_name: str, record_type: i64] : Blob name := net.encode_dns_name(domain_name) - out : Blob = must(Blob.alloc?(12 + name->size + 4)) + out := Blob.alloc(12 + name->size + 4) // header id := math.abs(os.urandom_i64() % 65536) @@ -197,14 +185,13 @@ func net.build_dns_query[domain_name: str, record_type: i64] : Blob return out // TODO: dont resolve if its already an IP -func net.resolve?[domain: str] : i64 - err.clear() +func net.resolve[domain: str] : i64, bool query := net.build_dns_query(domain, DNS_TYPE_A) // TODO: this probably shouldnt be hardcoded - s := net.create_udp_client?(net.pack_addr(1, 1, 1, 1), 53) - if err.check() - return -1 + ~s, ok := net.create_udp_client(net.pack_addr(1, 1, 1, 1), 53) + if !ok + return -1, false net.udp_send_to(s, s->addr, query->data, query->size) Blob.free(query) @@ -224,4 +211,4 @@ func net.resolve?[domain: str] : i64 out := net.pack_addr(pkt->data[pos] as i64, pkt->data[pos+1] as i64, pkt->data[pos+2] as i64, pkt->data[pos+3] as i64) net.UDPPacket.free(pkt) - return out + return out, true diff --git a/src/std/std.zr b/src/std/std.zr index 331f408..5885faa 100644 --- a/src/std/std.zr +++ b/src/std/std.zr @@ -1,33 +1,3 @@ -const ERR_NONE = 0 -const ERR_SYSCALL_FAILED = 1 -const ERR_OPEN_FAILED = 2 -const ERR_READ_FAILED = 3 -const ERR_WRITE_FAILED = 4 -const ERR_ALLOC_FAILED = 5 -const ERR_CONNECTION_FAILED = 6 -const ERR_KEY_ERROR = 7 - -func err.code[] : i64 - return mem.read64(_builtin_err_code()) - -func err.msg[] : str - return mem.read64(_builtin_err_msg()) as str - -func err.check[] : bool - return err.code() != 0 - -func err.clear[] : void - err.set(0, 0 as str) - -func err.set[code: i64, msg: str] : void - mem.write64(_builtin_err_code(), code) - mem.write64(_builtin_err_msg(), msg) - -func must[x: any] : any - if err.check() - panic(err.msg()) - return x - func panic[msg: str] : void io.print("PANIC: ") io.println(msg) @@ -62,8 +32,7 @@ func mem._split_block[blk: mem.Block, needed: i64] : void blk->size = needed blk->next = new_blk -func mem._request_space?[size: i64] : mem.Block - err.clear() +func mem._request_space[size: i64] : mem.Block needed := size + MEM_BLOCK_SIZE alloc_size := (needed + 4095) & -4096 @@ -72,8 +41,7 @@ func mem._request_space?[size: i64] : mem.Block // fd = -1, offset = 0 blk := _builtin_syscall(SYS_mmap, 0, alloc_size, 3, 34, -1, 0) as mem.Block if (blk as ptr as i64) == -1 - err.set(ERR_ALLOC_FAILED, "mem._request_space: mmap failed") - return 0 as mem.Block + panic("mem._request_space: failed to mmap") blk->size = alloc_size - MEM_BLOCK_SIZE blk->free = false @@ -88,11 +56,9 @@ func mem._request_space?[size: i64] : mem.Block mem.write64(_builtin_heap_tail(), blk) return blk -func mem.alloc?[size: i64] : ptr - err.clear() +func mem.alloc[size: i64] : ptr if size <= 0 - err.set(ERR_ALLOC_FAILED, "mem.alloc? called with non-positive size") - return 0 as ptr + panic("mem.alloc: called with nonpositive size") size = mem._align(size) @@ -104,9 +70,7 @@ func mem.alloc?[size: i64] : ptr return cur as ptr + MEM_BLOCK_SIZE cur = cur->next - blk := mem._request_space?(size) - if err.check() - return 0 as ptr + blk := mem._request_space(size) if !mem.read64(_builtin_heap_head()) mem.write64(_builtin_heap_head(), blk) @@ -115,9 +79,6 @@ func mem.alloc?[size: i64] : ptr return blk as ptr + MEM_BLOCK_SIZE -func mem.alloc[size: i64] : ptr - return must(mem.alloc?(size)) - func mem.free[x: any] : void if x == 0 return 0 @@ -163,14 +124,12 @@ func mem.free[x: any] : void mem.write64(_builtin_heap_tail(), blk->prev) _builtin_syscall(SYS_munmap, blk, block_total) -func mem.realloc?[x: ptr, new_size: i64] : ptr - err.clear() +func mem.realloc[x: ptr, new_size: i64] : ptr if !x - return mem.alloc?(new_size) + return mem.alloc(new_size) if new_size < 0 - err.set(ERR_ALLOC_FAILED, "mem.realloc? called with negative size") - return 0 as ptr + panic("mem.realloc: called with negative new_size") if new_size == 0 mem.free(x) @@ -198,9 +157,7 @@ func mem.realloc?[x: ptr, new_size: i64] : ptr mem._split_block(blk, new_size) return x - new_ptr := mem.alloc?(new_size) - if err.check() - return 0 as ptr + new_ptr := mem.alloc(new_size) mem.copy(x, new_ptr, math.min(blk->size, new_size)) mem.free(x) @@ -333,21 +290,17 @@ func io.read_line[]: str if n < 0 n = 0 buffer[n] = 0 - buffer = must(mem.realloc?(buffer as ptr, n + 1)) + buffer = mem.realloc(buffer as ptr, n + 1) as str return buffer struct Blob data: ptr size: i64 -func Blob.alloc?[size: i64] : Blob - err.clear() +func Blob.alloc[size: i64] : Blob buffer := new* Blob buffer->size = size - buffer->data = mem.alloc?(size) - if err.check() - mem.free(buffer) - return 0 as Blob + buffer->data = mem.alloc(size) return buffer func Blob.free[buf: Blob] : void @@ -373,74 +326,58 @@ func io.is_a_directory[path: str] : bool mem.free(st) return out -func io.read_text_file?[path: str] : str - err.clear() +func io.read_text_file[path: str] : str, bool fd := _builtin_syscall(SYS_openat, -100, path, 0, 0) if fd < 0 - err.set(ERR_OPEN_FAILED, "io.read_text_file?: failed to open file") - return 0 as str + return 0 as str, false size := _builtin_syscall(SYS_lseek, fd, 0, 2) _builtin_syscall(SYS_lseek, fd, 0, 0) - buffer := mem.alloc?(size + 1) as str - if err.check() - _builtin_syscall(SYS_close, fd) - return 0 as str - + buffer := mem.alloc(size + 1) n := _builtin_syscall(SYS_read, fd, buffer, size) _builtin_syscall(SYS_close, fd) if n != size mem.free(buffer) - err.set(ERR_READ_FAILED, "io.read_text_file?: failed to read file") - return 0 as str + return 0 as str, false buffer[n] = 0 - return buffer + return buffer as str, true -func io.read_binary_file?[path: str] : Blob - err.clear() +func io.read_binary_file[path: str] : Blob, bool fd := _builtin_syscall(SYS_openat, -100, path, 0, 0) if fd < 0 - err.set(ERR_OPEN_FAILED, "io.read_binary_file?: failed to open file") - return 0 as Blob + return 0 as Blob, false buf := new* Blob buf->size = _builtin_syscall(SYS_lseek, fd, 0, 2) _builtin_syscall(SYS_lseek, fd, 0, 0) - buf->data = mem.alloc?(buf->size) - if err.check() - Blob.free(buf) - _builtin_syscall(SYS_close, fd) - return 0 as Blob + buf->data = mem.alloc(buf->size) n := _builtin_syscall(SYS_read, fd, buf->data, buf->size) _builtin_syscall(SYS_close, fd) if n != buf->size Blob.free(buf) - err.set(ERR_READ_FAILED, "io.read_binary_file?: failed to read file") - return 0 as Blob + return 0 as Blob, false - return buf + return buf, true -func io.write_file?[path: str, content: str] : void - io.write_binary_file?(path, content as ptr, str.len(content)) +func io.write_file[path: str, content: str] : bool + return io.write_binary_file(path, content as ptr, str.len(content)) -func io.write_binary_file?[path: str, content: ptr, size: i64] : void - err.clear() +func io.write_binary_file[path: str, content: ptr, size: i64] : bool fd := _builtin_syscall(SYS_openat, -100, path, 0x241, 0o644) if fd < 0 - err.set(ERR_OPEN_FAILED, "io.write_binary_file?: failed to open file") - return 0 + return false n := _builtin_syscall(SYS_write, fd, content, size) _builtin_syscall(SYS_close, fd) if n != size - err.set(ERR_WRITE_FAILED, "io.write_binary_file?: failed to write file") - return 0 + return false + return true func str.len[s: str] : i64 i := 0 @@ -785,7 +722,7 @@ func array.new[] : Array func array.new_preallocated_and_zeroed[size: i64] : Array xs := new* Array if size > 0 - xs->data = must(mem.realloc?(xs->data, size * 8)) as ptr + xs->data = mem.realloc(xs->data, size * 8) mem.zero(xs->data, size * 8) xs->size = size xs->capacity = size @@ -806,7 +743,7 @@ func array.push[xs: Array, x: any] : void new_capacity := 4 if xs->capacity != 0 new_capacity = xs->capacity * 2 - xs->data = must(mem.realloc?(xs->data, new_capacity * 8)) + xs->data = mem.realloc(xs->data, new_capacity * 8) xs->capacity = new_capacity mem.write64(xs->data + xs->size * 8, x) @@ -872,18 +809,16 @@ func HashMap.insert[map: HashMap, key: str, value: any] : void new_node->next = array.nth(map->table, index) array.set(map->table, index, new_node) -func HashMap.get?[map: HashMap, key: str] : any - err.clear() +func HashMap.get[map: HashMap, key: str] : any, bool index := HashMap._djb2(key) current : HashMap._Node = array.nth(map->table, index) while current as ptr if str.equal(current->key, key) - return current->value + return current->value, true current = current->next - err.set(ERR_KEY_ERROR, "key not found") - return 0 + return 0 as any, false func HashMap.delete[map: HashMap, key: str] : void index := HashMap._djb2(key) @@ -990,30 +925,23 @@ func os.sleep[ms: i64] : void req->tv_nsec = (ms % 1000) * 1000000 _builtin_syscall(SYS_nanosleep, req, 0) -func os.urandom?[n: i64]: ptr - err.clear() +func os.urandom[n: i64]: ptr buffer := mem.alloc(n) - if err.check() - return 0 as ptr fd := _builtin_syscall(SYS_openat, -100, "/dev/urandom", 0, 0) if fd < 0 - mem.free(buffer) - err.set(ERR_OPEN_FAILED, "os.urandom?: failed to open /dev/urandom") - return 0 as ptr + panic("os.urandom: failed to open /dev/urandom") bytes_read := _builtin_syscall(SYS_read, fd, buffer, n) _builtin_syscall(SYS_close, fd) if n != bytes_read - mem.free(buffer) - err.set(ERR_READ_FAILED, "os.urandom?: failed to read /dev/urandom") - return 0 as ptr + panic("os.urandom: failed to read /dev/urandom") return buffer func os.urandom_i64[]: i64 - buffer : ptr = must(os.urandom?(8)) + buffer := os.urandom(8) n := mem.read64(buffer) mem.free(buffer) return n @@ -1029,12 +957,10 @@ func os.time[] : i64 return out // voodoo magic -func os.run_shell_command?[command: str] : i64 - err.clear() +func os.run_shell_command[command: str] : i64, bool pid := _builtin_syscall(SYS_fork) if pid < 0 - err.set(ERR_SYSCALL_FAILED, "os.run_shell_command?: failed to fork") - return -1 + return -1, false if pid == 0 argv := ["sh", "-c", command, 0] // gets freed after child process exits @@ -1044,21 +970,18 @@ func os.run_shell_command?[command: str] : i64 status := 0 wp := _builtin_syscall(SYS_wait4, pid, ^status, 0, 0) if wp < 0 - err.set(ERR_SYSCALL_FAILED, "os.run_shell_command?: wait() failed") - return -1 + return -1, false st := status & 0xffffffff if (st & 0x7f) == 0 - return (st >> 8) & 0xff + return (st >> 8) & 0xff, true else - return -(st & 0x7f) + return -(st & 0x7f), true -func os.list_directory?[path: str] : Array - err.clear() +func os.list_directory[path: str] : Array, bool fd := _builtin_syscall(SYS_openat, -100, path, 0, 0) if fd < 0 - err.set(ERR_OPEN_FAILED, "os.list_directory?: failed to open dir") - return 0 as Array + return 0 as Array, false files := [] buf := mem.alloc(1024) @@ -1072,8 +995,7 @@ func os.list_directory?[path: str] : Array array.free(files) _builtin_syscall(SYS_close, fd) - err.set(ERR_SYSCALL_FAILED, "os.list_directory?: getdents64() failed") - return 0 as Array + return 0 as Array, false else if n == 0 break @@ -1096,4 +1018,4 @@ func os.list_directory?[path: str] : Array mem.free(buf) _builtin_syscall(SYS_close, fd) - return files + return files, true diff --git a/src/symbol_table.rs b/src/symbol_table.rs index 7f37fe0..ccbbf2b 100644 --- a/src/symbol_table.rs +++ b/src/symbol_table.rs @@ -46,8 +46,6 @@ impl SymbolTable { functions: HashMap::from([ ("_builtin_heap_head".into(), FnType::new("ptr", vec![])), ("_builtin_heap_tail".into(), FnType::new("ptr", vec![])), - ("_builtin_err_code".into(), FnType::new("ptr", vec![])), - ("_builtin_err_msg".into(), FnType::new("ptr", vec![])), ("_builtin_read64".into(), FnType::new("i64", vec!["ptr"])), ( "_builtin_set64".into(), diff --git a/src/tokenizer.rs b/src/tokenizer.rs index 680fc8f..bd08ef2 100644 --- a/src/tokenizer.rs +++ b/src/tokenizer.rs @@ -348,11 +348,7 @@ impl Tokenizer { } fn scan_identifier(&mut self) -> Result<(), ZernError> { - while self.peek().is_alphanumeric() - || self.peek() == '_' - || self.peek() == '.' - || self.peek() == '?' - { + while self.peek().is_alphanumeric() || self.peek() == '_' || self.peek() == '.' { self.advance(); } diff --git a/test.zr b/test.zr index bffa770..5236320 100644 --- a/test.zr +++ b/test.zr @@ -10,7 +10,8 @@ func run_test[x: str] : void io.printf("Building %s...\n", x) build_start_time := os.time() - if must(os.run_shell_command?(str.concat("./target/release/zern ", x))) != 0 + ~status, ok := os.run_shell_command(str.concat("./target/release/zern ", x)) + if !ok || status != 0 os.exit(1) build_end_time := os.time() @@ -30,21 +31,26 @@ func run_test[x: str] : void run_cmd = str.concat(run_cmd, " http://example.com") run_start_time := os.time() - if must(os.run_shell_command?(run_cmd)) != 0 + ~status, ok := os.run_shell_command(run_cmd) + if !ok || status != 0 os.exit(1) run_end_time := os.time() io.printf("Running %s took %dms\n", x, run_end_time - run_start_time) func run_directory[dir: str] : void - files : Array = must(os.list_directory?(dir)) + ~files, ok := os.list_directory(dir) + if !ok + panic("failed to open test directory") for i in 0..files->size run_test(str.concat(dir, array.nth(files, i))) array.free(files) func main[] : i64 - must(os.run_shell_command?("cargo build --release")) + ~status, ok := os.run_shell_command("cargo build --release") + if !ok || status != 0 + os.exit(1) run_directory("examples/") run_directory("examples/puzzles/")