more error handling
This commit is contained in:
@@ -15,7 +15,7 @@ func part2[l1: Array, l2: Array] : void
|
||||
io.println_i64(out)
|
||||
|
||||
func main[] : i64
|
||||
let lines: Array = must(io.read_file?("input.txt")) |> str.split("\n")
|
||||
let lines: Array = must(io.read_text_file?("input.txt")) |> str.split("\n")
|
||||
|
||||
let l1: Array = []
|
||||
let l2: Array = []
|
||||
|
||||
@@ -40,7 +40,7 @@ func part2[data: Array] : void
|
||||
io.println_i64(out)
|
||||
|
||||
func main[] : i64
|
||||
let lines: Array = must(io.read_file?("input.txt")) |> str.split("\n")
|
||||
let lines: Array = must(io.read_text_file?("input.txt")) |> str.split("\n")
|
||||
|
||||
let data: Array = []
|
||||
for i in 0..lines->size
|
||||
|
||||
@@ -56,7 +56,7 @@ func part2[lines: Array] : void
|
||||
io.println_i64(out)
|
||||
|
||||
func main[] : i64
|
||||
let lines: Array = must(io.read_file?("input.txt")) |> str.split("\n")
|
||||
let lines: Array = must(io.read_text_file?("input.txt")) |> str.split("\n")
|
||||
|
||||
part1(lines)
|
||||
part2(lines)
|
||||
|
||||
@@ -47,7 +47,7 @@ func part2[updates: Array, rules_left: Array, rules_right: Array] : void
|
||||
io.println_i64(out)
|
||||
|
||||
func main[] : i64
|
||||
let data: Array = must(io.read_file?("input.txt")) |> str.split("\n\n")
|
||||
let data: Array = must(io.read_text_file?("input.txt")) |> str.split("\n\n")
|
||||
|
||||
let rules_left: Array = []
|
||||
let rules_right: Array = []
|
||||
|
||||
@@ -61,7 +61,7 @@ func part2[equations: Array] : void
|
||||
io.println_i64(out)
|
||||
|
||||
func main[] : i64
|
||||
let lines: Array = must(io.read_file?("input.txt")) |> str.split("\n")
|
||||
let lines: Array = must(io.read_text_file?("input.txt")) |> str.split("\n")
|
||||
let equations: Array = []
|
||||
|
||||
for i in 0..lines->size
|
||||
|
||||
@@ -47,7 +47,7 @@ func part2[lines: Array] : void
|
||||
io.println_i64(password)
|
||||
|
||||
func main[] : i64
|
||||
let lines: Array = must(io.read_file?("input.txt")) |> str.split("\n")
|
||||
let lines: Array = must(io.read_text_file?("input.txt")) |> str.split("\n")
|
||||
|
||||
part1(lines)
|
||||
part2(lines)
|
||||
|
||||
@@ -54,7 +54,7 @@ func part2[ranges: Array] : void
|
||||
io.println_i64(sum)
|
||||
|
||||
func main[] : i64
|
||||
let ranges: Array = must(io.read_file?("input.txt")) |> str.split(",")
|
||||
let ranges: Array = must(io.read_text_file?("input.txt")) |> str.split(",")
|
||||
|
||||
part1(ranges)
|
||||
part2(ranges)
|
||||
|
||||
@@ -45,7 +45,7 @@ func part2[lines: Array] : void
|
||||
io.println_i64(sum)
|
||||
|
||||
func main[] : i64
|
||||
let lines: Array = must(io.read_file?("input.txt")) |> str.split("\n")
|
||||
let lines: Array = must(io.read_text_file?("input.txt")) |> str.split("\n")
|
||||
|
||||
part1(lines)
|
||||
part2(lines)
|
||||
|
||||
@@ -746,6 +746,7 @@ _builtin_environ:
|
||||
Expr::New(struct_name) => {
|
||||
let struct_fields = &self.analyzer.structs[&struct_name.lexeme];
|
||||
|
||||
// TODO: panic on mem.alloc error
|
||||
let memory_size = struct_fields.len() * 8;
|
||||
emit!(&mut self.output, " mov rdi, {}", memory_size);
|
||||
emit!(&mut self.output, " call mem.alloc");
|
||||
|
||||
@@ -158,7 +158,7 @@ const DNS_RECURSION_DESIRED = 256
|
||||
|
||||
func net.encode_dns_name[domain: str] : io.Buffer
|
||||
let domain_len: i64 = str.len(domain)
|
||||
let buf: io.Buffer = io.Buffer.alloc(domain_len + 2)
|
||||
let buf: io.Buffer = must(io.Buffer.alloc?(domain_len + 2))
|
||||
let out_pos: i64 = 0
|
||||
let part_start: i64 = 0
|
||||
let i: i64 = 0
|
||||
@@ -177,7 +177,7 @@ func net.encode_dns_name[domain: str] : io.Buffer
|
||||
|
||||
func net.build_dns_query[domain_name: str, record_type: i64] : io.Buffer
|
||||
let name: io.Buffer = net.encode_dns_name(domain_name)
|
||||
let out: io.Buffer = io.Buffer.alloc(12 + name->size + 4)
|
||||
let out: io.Buffer = must(io.Buffer.alloc?(12 + name->size + 4))
|
||||
|
||||
// header
|
||||
let id: i64 = math.abs(os.urandom_i64() % 65536)
|
||||
|
||||
118
src/std/std.zr
118
src/std/std.zr
@@ -90,7 +90,8 @@ func mem._request_space?[size: i64] : mem.Block
|
||||
|
||||
func mem.alloc?[size: i64] : ptr
|
||||
err.clear()
|
||||
if size == 0
|
||||
if size <= 0
|
||||
err.set(ERR_ALLOC_FAILED, "mem.alloc? called with non-positive size")
|
||||
return 0
|
||||
|
||||
size = mem._align(size)
|
||||
@@ -168,6 +169,10 @@ func mem.realloc?[x: ptr, new_size: i64] : ptr
|
||||
if !x
|
||||
return mem.alloc?(new_size)
|
||||
|
||||
if new_size < 0
|
||||
err.set(ERR_ALLOC_FAILED, "mem.realloc? called with negative size")
|
||||
return 0
|
||||
|
||||
if new_size == 0
|
||||
mem.free(x)
|
||||
return 0
|
||||
@@ -195,7 +200,7 @@ func mem.realloc?[x: ptr, new_size: i64] : ptr
|
||||
mem._split_block(blk, new_size)
|
||||
return x
|
||||
|
||||
let new_ptr: ptr = mem.alloc(new_size)
|
||||
let new_ptr: ptr = mem.alloc?(new_size)
|
||||
if err.check()
|
||||
return 0
|
||||
|
||||
@@ -211,10 +216,15 @@ func mem.zero[x: ptr, size: i64] : void
|
||||
for i in 0..size
|
||||
x[i] = 0
|
||||
|
||||
// TODO: handle overlapping src & dst
|
||||
func mem.copy[src: ptr, dst: ptr, n: i64] : void
|
||||
for i in 0..n
|
||||
dst[i] = src[i]
|
||||
if dst > src
|
||||
let i: i64 = n - 1
|
||||
while i >= 0
|
||||
dst[i] = src[i]
|
||||
i = i - 1
|
||||
else
|
||||
for i in 0..n
|
||||
dst[i] = src[i]
|
||||
|
||||
func mem.read8[x: ptr] : u8
|
||||
return x[0]
|
||||
@@ -323,16 +333,21 @@ func io.read_line[]: str
|
||||
if n < 0
|
||||
n = 0
|
||||
buffer[n] = 0
|
||||
buffer = must(mem.realloc?(buffer, n + 1))
|
||||
return buffer
|
||||
|
||||
struct io.Buffer
|
||||
data: ptr
|
||||
size: i64
|
||||
|
||||
func io.Buffer.alloc[size: i64] : io.Buffer
|
||||
func io.Buffer.alloc?[size: i64] : io.Buffer
|
||||
err.clear()
|
||||
let buffer: io.Buffer = new io.Buffer
|
||||
buffer->size = size
|
||||
buffer->data = mem.alloc(size)
|
||||
buffer->data = mem.alloc?(size)
|
||||
if err.check()
|
||||
mem.free(buffer)
|
||||
return 0
|
||||
return buffer
|
||||
|
||||
func io.Buffer.free[buf: io.Buffer] : void
|
||||
@@ -342,23 +357,27 @@ func io.Buffer.free[buf: io.Buffer] : void
|
||||
func io.file_exists[path: str] : bool
|
||||
return _builtin_syscall(SYS_faccessat, -100, path, 0, 0) == 0
|
||||
|
||||
func io.read_file?[path: str] : str
|
||||
func io.read_text_file?[path: str] : str
|
||||
err.clear()
|
||||
let fd: i64 = _builtin_syscall(SYS_openat, -100, path, 0, 0)
|
||||
if fd < 0
|
||||
err.set(ERR_OPEN_FAILED, "io.read_file?: failed to open file")
|
||||
err.set(ERR_OPEN_FAILED, "io.read_text_file?: failed to open file")
|
||||
return 0
|
||||
|
||||
let size: i64 = _builtin_syscall(SYS_lseek, fd, 0, 2)
|
||||
_builtin_syscall(SYS_lseek, fd, 0, 0)
|
||||
|
||||
let buffer: str = mem.alloc(size + 1)
|
||||
let buffer: str = mem.alloc?(size + 1)
|
||||
if err.check()
|
||||
_builtin_syscall(SYS_close, fd)
|
||||
return 0
|
||||
|
||||
let n: i64 = _builtin_syscall(SYS_read, fd, buffer, size)
|
||||
_builtin_syscall(SYS_close, fd)
|
||||
|
||||
if n < 0
|
||||
if n != size
|
||||
mem.free(buffer)
|
||||
err.set(ERR_READ_FAILED, "io.read_file?: failed to read file")
|
||||
err.set(ERR_READ_FAILED, "io.read_text_file?: failed to read file")
|
||||
return 0
|
||||
|
||||
buffer[n] = 0
|
||||
@@ -371,30 +390,28 @@ func io.read_binary_file?[path: str] : io.Buffer
|
||||
err.set(ERR_OPEN_FAILED, "io.read_binary_file?: failed to open file")
|
||||
return 0
|
||||
|
||||
let buffer: io.Buffer = new io.Buffer
|
||||
buffer->size = _builtin_syscall(SYS_lseek, fd, 0, 2)
|
||||
let buf: io.Buffer = new io.Buffer
|
||||
buf->size = _builtin_syscall(SYS_lseek, fd, 0, 2)
|
||||
_builtin_syscall(SYS_lseek, fd, 0, 0)
|
||||
|
||||
buffer->data = mem.alloc(buffer->size)
|
||||
let n: i64 = _builtin_syscall(SYS_read, fd, buffer->data, buffer->size)
|
||||
buf->data = mem.alloc?(buf->size)
|
||||
if err.check()
|
||||
io.Buffer.free(buf)
|
||||
_builtin_syscall(SYS_close, fd)
|
||||
return 0
|
||||
|
||||
let n: i64 = _builtin_syscall(SYS_read, fd, buf->data, buf->size)
|
||||
_builtin_syscall(SYS_close, fd)
|
||||
|
||||
if n < 0
|
||||
mem.free(buffer)
|
||||
if n != buf->size
|
||||
io.Buffer.free(buf)
|
||||
err.set(ERR_READ_FAILED, "io.read_binary_file?: failed to read file")
|
||||
return 0
|
||||
|
||||
return buffer
|
||||
return buf
|
||||
|
||||
func io.write_file?[path: str, content: str] : void
|
||||
err.clear()
|
||||
let fd: i64 = _builtin_syscall(SYS_openat, -100, path, 0x241, 0o644)
|
||||
if fd < 0
|
||||
err.set(ERR_OPEN_FAILED, "io.write_file?: failed to open file")
|
||||
return 0
|
||||
|
||||
_builtin_syscall(SYS_write, fd, content, str.len(content))
|
||||
_builtin_syscall(SYS_close, fd)
|
||||
io.write_binary_file?(path, content, str.len(content))
|
||||
|
||||
func io.write_binary_file?[path: str, content: ptr, size: i64] : void
|
||||
err.clear()
|
||||
@@ -403,8 +420,11 @@ func io.write_binary_file?[path: str, content: ptr, size: i64] : void
|
||||
err.set(ERR_OPEN_FAILED, "io.write_binary_file?: failed to open file")
|
||||
return 0
|
||||
|
||||
_builtin_syscall(SYS_write, fd, content, size)
|
||||
let n: i64 = _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
|
||||
|
||||
func str.len[s: str] : i64
|
||||
let i = 0
|
||||
@@ -491,7 +511,9 @@ func str.substr[s: str, start: i64, length: i64] : str
|
||||
func str.trim[s: str] : str
|
||||
let len: i64 = str.len(s)
|
||||
if len == 0
|
||||
return s
|
||||
let out: str = mem.alloc(1)
|
||||
out[0] = 0
|
||||
return out
|
||||
|
||||
let start = 0
|
||||
let end: i64 = len - 1
|
||||
@@ -665,6 +687,8 @@ func str.hex_decode[s: str] : str
|
||||
return out
|
||||
|
||||
func math.gcd[a: i64, b: i64] : i64
|
||||
a = math.abs(a)
|
||||
b = math.abs(b)
|
||||
while b != 0
|
||||
let tmp: i64 = b
|
||||
b = a % b
|
||||
@@ -682,6 +706,8 @@ func math.max[a: i64, b: i64] : i64
|
||||
return b
|
||||
|
||||
func math.abs[n: i64] : i64
|
||||
if n == -9223372036854775808
|
||||
panic("MIN_I64 passed to math.abs")
|
||||
if n < 0
|
||||
return -n
|
||||
return n
|
||||
@@ -695,13 +721,15 @@ func math.sign[n: i64] : i64
|
||||
return 0
|
||||
|
||||
func math.pow[b: i64, e: i64] : i64
|
||||
if e < 0
|
||||
panic("negative exponent passed to math.pow")
|
||||
let out = 1
|
||||
for i in 0..e
|
||||
out = out * b
|
||||
return out
|
||||
|
||||
func math.lcm[a: i64, b: i64] : i64
|
||||
return (a * b) / math.gcd(a, b)
|
||||
return (a / math.gcd(a, b)) * b
|
||||
|
||||
func math.isqrt[n: i64] : i64
|
||||
if n < 0
|
||||
@@ -876,6 +904,7 @@ func os.urandom?[n: i64]: ptr
|
||||
|
||||
let fd: i64 = _builtin_syscall(SYS_openat, -100, "/dev/urandom", 0, 0)
|
||||
if fd < 0
|
||||
mem.free(buffer)
|
||||
err.set(ERR_READ_FAILED, "os.urandom?: failed to open /dev/urandom")
|
||||
return 0
|
||||
|
||||
@@ -883,6 +912,7 @@ func os.urandom?[n: i64]: ptr
|
||||
_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
|
||||
|
||||
@@ -907,8 +937,13 @@ func os.time[] : i64
|
||||
return out
|
||||
|
||||
// voodoo magic
|
||||
func os.run_shell_command[command: str] : i64
|
||||
func os.run_shell_command?[command: str] : i64
|
||||
err.clear()
|
||||
let pid: i64 = _builtin_syscall(SYS_fork)
|
||||
if pid < 0
|
||||
err.set(ERR_SYSCALL_FAILED, "os.run_shell_command?: failed to fork")
|
||||
return -1
|
||||
|
||||
if pid == 0
|
||||
let argv: Array = ["sh", "-c", command, 0] // gets freed after child process exits
|
||||
_builtin_syscall(SYS_execve, "/bin/sh", argv->data, _builtin_environ())
|
||||
@@ -916,7 +951,8 @@ func os.run_shell_command[command: str] : i64
|
||||
else
|
||||
let status = 0
|
||||
let wp: i64 = _builtin_syscall(SYS_wait4, pid, ^status, 0, 0)
|
||||
if wp == -1
|
||||
if wp < 0
|
||||
err.set(ERR_SYSCALL_FAILED, "os.run_shell_command?: wait() failed")
|
||||
return -1
|
||||
let st: i64 = status & 0xffffffff
|
||||
|
||||
@@ -925,16 +961,28 @@ func os.run_shell_command[command: str] : i64
|
||||
else
|
||||
return -(st & 0x7f)
|
||||
|
||||
func os.list_directory[path: str] : Array
|
||||
func os.list_directory?[path: str] : Array
|
||||
err.clear()
|
||||
let fd: i64 = _builtin_syscall(SYS_openat, -100, path, 0, 0)
|
||||
if fd < 0
|
||||
return []
|
||||
err.set(ERR_OPEN_FAILED, "os.list_directory?: failed to open dir")
|
||||
return 0
|
||||
|
||||
let files: Array = []
|
||||
let buf: ptr = mem.alloc(1024)
|
||||
while true
|
||||
let n: i64 = _builtin_syscall(SYS_getdents64, fd, buf, 1024)
|
||||
if n <= 0
|
||||
if n < 0
|
||||
mem.free(buf)
|
||||
|
||||
for i in 0..files->size
|
||||
mem.free(array.nth(files, i))
|
||||
array.free(files)
|
||||
|
||||
_builtin_syscall(SYS_close, fd)
|
||||
err.set(ERR_SYSCALL_FAILED, "os.list_directory?: getdents64() failed")
|
||||
return 0
|
||||
else if n == 0
|
||||
break
|
||||
|
||||
let pos = 0
|
||||
|
||||
8
test.zr
8
test.zr
@@ -14,7 +14,7 @@ func run_test[x: str] : void
|
||||
io.print("... ")
|
||||
|
||||
let build_start_time: i64 = os.time()
|
||||
if os.run_shell_command(str.concat("./target/release/zern ", x)) != 0
|
||||
if must(os.run_shell_command?(str.concat("./target/release/zern ", x))) != 0
|
||||
os.exit(1)
|
||||
let build_end_time: i64 = os.time()
|
||||
|
||||
@@ -39,7 +39,7 @@ func run_test[x: str] : void
|
||||
run_cmd = str.concat(run_cmd, " test.zr")
|
||||
|
||||
let run_start_time: i64 = os.time()
|
||||
if os.run_shell_command(run_cmd) != 0
|
||||
if must(os.run_shell_command?(run_cmd)) != 0
|
||||
os.exit(1)
|
||||
let run_end_time: i64 = os.time()
|
||||
|
||||
@@ -50,14 +50,14 @@ func run_test[x: str] : void
|
||||
io.println("ms")
|
||||
|
||||
func run_directory[dir: str] : void
|
||||
let files: Array = os.list_directory(dir)
|
||||
let files: Array = must(os.list_directory?(dir))
|
||||
for i in 0..files->size
|
||||
run_test(str.concat(dir, array.nth(files, i)))
|
||||
|
||||
array.free(files)
|
||||
|
||||
func main[] : i64
|
||||
os.run_shell_command("cargo build --release")
|
||||
must(os.run_shell_command?("cargo build --release"))
|
||||
|
||||
run_directory("examples/")
|
||||
run_directory("examples/puzzles/")
|
||||
|
||||
Reference in New Issue
Block a user