error handling
This commit is contained in:
@@ -26,15 +26,9 @@ func main[argc: i64, argv: ptr] : i64
|
|||||||
if i < url_len
|
if i < url_len
|
||||||
path = str.substr(url, i, url_len - i)
|
path = str.substr(url, i, url_len - i)
|
||||||
|
|
||||||
let addr: i64 = net.resolve(host)
|
let addr: i64 = must(net.resolve?(host))
|
||||||
if addr <= 0
|
|
||||||
io.println("ERROR: domain resolution failed")
|
|
||||||
return 1
|
|
||||||
|
|
||||||
let s: i64 = net.connect(addr, 80)
|
let s: i64 = must(net.connect?(addr, 80))
|
||||||
if s < 0
|
|
||||||
io.println("ERROR: connection failed")
|
|
||||||
return 1
|
|
||||||
|
|
||||||
// TODO: add string builder to std
|
// TODO: add string builder to std
|
||||||
let req: str = "GET "
|
let req: str = "GET "
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ func part2[l1: Array, l2: Array] : void
|
|||||||
io.println_i64(out)
|
io.println_i64(out)
|
||||||
|
|
||||||
func main[] : i64
|
func main[] : i64
|
||||||
let lines: Array = io.read_file("input.txt") |> str.split("\n")
|
let lines: Array = must(io.read_file?("input.txt")) |> str.split("\n")
|
||||||
|
|
||||||
let l1: Array = []
|
let l1: Array = []
|
||||||
let l2: Array = []
|
let l2: Array = []
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ func part2[data: Array] : void
|
|||||||
io.println_i64(out)
|
io.println_i64(out)
|
||||||
|
|
||||||
func main[] : i64
|
func main[] : i64
|
||||||
let lines: Array = io.read_file("input.txt") |> str.split("\n")
|
let lines: Array = must(io.read_file?("input.txt")) |> str.split("\n")
|
||||||
|
|
||||||
let data: Array = []
|
let data: Array = []
|
||||||
for i in 0..lines->size
|
for i in 0..lines->size
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ func part2[lines: Array] : void
|
|||||||
io.println_i64(out)
|
io.println_i64(out)
|
||||||
|
|
||||||
func main[] : i64
|
func main[] : i64
|
||||||
let lines: Array = io.read_file("input.txt") |> str.split("\n")
|
let lines: Array = must(io.read_file?("input.txt")) |> str.split("\n")
|
||||||
|
|
||||||
part1(lines)
|
part1(lines)
|
||||||
part2(lines)
|
part2(lines)
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ func part2[updates: Array, rules_left: Array, rules_right: Array] : void
|
|||||||
io.println_i64(out)
|
io.println_i64(out)
|
||||||
|
|
||||||
func main[] : i64
|
func main[] : i64
|
||||||
let data: Array = io.read_file("input.txt") |> str.split("\n\n")
|
let data: Array = must(io.read_file?("input.txt")) |> str.split("\n\n")
|
||||||
|
|
||||||
let rules_left: Array = []
|
let rules_left: Array = []
|
||||||
let rules_right: Array = []
|
let rules_right: Array = []
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ func part2[equations: Array] : void
|
|||||||
io.println_i64(out)
|
io.println_i64(out)
|
||||||
|
|
||||||
func main[] : i64
|
func main[] : i64
|
||||||
let lines: Array = io.read_file("input.txt") |> str.split("\n")
|
let lines: Array = must(io.read_file?("input.txt")) |> str.split("\n")
|
||||||
let equations: Array = []
|
let equations: Array = []
|
||||||
|
|
||||||
for i in 0..lines->size
|
for i in 0..lines->size
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ func part2[lines: Array] : void
|
|||||||
io.println_i64(password)
|
io.println_i64(password)
|
||||||
|
|
||||||
func main[] : i64
|
func main[] : i64
|
||||||
let lines: Array = io.read_file("input.txt") |> str.split("\n")
|
let lines: Array = must(io.read_file?("input.txt")) |> str.split("\n")
|
||||||
|
|
||||||
part1(lines)
|
part1(lines)
|
||||||
part2(lines)
|
part2(lines)
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ func part2[ranges: Array] : void
|
|||||||
io.println_i64(sum)
|
io.println_i64(sum)
|
||||||
|
|
||||||
func main[] : i64
|
func main[] : i64
|
||||||
let ranges: Array = io.read_file("input.txt") |> str.split(",")
|
let ranges: Array = must(io.read_file?("input.txt")) |> str.split(",")
|
||||||
|
|
||||||
part1(ranges)
|
part1(ranges)
|
||||||
part2(ranges)
|
part2(ranges)
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ func part2[lines: Array] : void
|
|||||||
io.println_i64(sum)
|
io.println_i64(sum)
|
||||||
|
|
||||||
func main[] : i64
|
func main[] : i64
|
||||||
let lines: Array = io.read_file("input.txt") |> str.split("\n")
|
let lines: Array = must(io.read_file?("input.txt")) |> str.split("\n")
|
||||||
|
|
||||||
part1(lines)
|
part1(lines)
|
||||||
part2(lines)
|
part2(lines)
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
func main[] : i64
|
func main[] : i64
|
||||||
let s: i64 = net.listen(net.pack_addr(127, 0, 0, 1), 8000)
|
let s: i64 = must(net.listen?(net.pack_addr(127, 0, 0, 1), 8000))
|
||||||
if s < 0
|
|
||||||
panic("failed to bind a socket")
|
|
||||||
|
|
||||||
io.println("Listening on port 8000...")
|
io.println("Listening on port 8000...")
|
||||||
let resp: str = mem.alloc(60000)
|
let resp: str = mem.alloc(60000)
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
func main[] : i64
|
func main[] : i64
|
||||||
let s: i64 = net.udp_listen(net.pack_addr(127, 0, 0, 1), 8000)
|
let s: i64 = must(net.udp_listen?(net.pack_addr(127, 0, 0, 1), 8000))
|
||||||
if !s
|
|
||||||
panic("failed to bind a socket")
|
|
||||||
|
|
||||||
io.println("Listening on port 8000...")
|
io.println("Listening on port 8000...")
|
||||||
while true
|
while true
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ impl Analyzer {
|
|||||||
functions: HashMap::from([
|
functions: HashMap::from([
|
||||||
("_builtin_heap_head".into(), 0),
|
("_builtin_heap_head".into(), 0),
|
||||||
("_builtin_heap_tail".into(), 0),
|
("_builtin_heap_tail".into(), 0),
|
||||||
|
("_builtin_err_code".into(), 0),
|
||||||
|
("_builtin_err_msg".into(), 0),
|
||||||
("_builtin_read64".into(), 1),
|
("_builtin_read64".into(), 1),
|
||||||
("_builtin_set64".into(), 2),
|
("_builtin_set64".into(), 2),
|
||||||
("_builtin_syscall".into(), -1),
|
("_builtin_syscall".into(), -1),
|
||||||
|
|||||||
@@ -110,6 +110,8 @@ section .bss
|
|||||||
_heap_head: resq 1
|
_heap_head: resq 1
|
||||||
_heap_tail: resq 1
|
_heap_tail: resq 1
|
||||||
_environ: resq 1
|
_environ: resq 1
|
||||||
|
_err_code: resq 1
|
||||||
|
_err_msg: resq 1
|
||||||
|
|
||||||
section .text._builtin_heap_head
|
section .text._builtin_heap_head
|
||||||
_builtin_heap_head:
|
_builtin_heap_head:
|
||||||
@@ -121,6 +123,16 @@ _builtin_heap_tail:
|
|||||||
lea rax, [rel _heap_tail]
|
lea rax, [rel _heap_tail]
|
||||||
ret
|
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
|
section .text._builtin_read64
|
||||||
_builtin_read64:
|
_builtin_read64:
|
||||||
mov rax, qword [rdi]
|
mov rax, qword [rdi]
|
||||||
|
|||||||
@@ -4,14 +4,17 @@ const SOCK_DGRAM = 2
|
|||||||
const SOL_SOCKET = 1
|
const SOL_SOCKET = 1
|
||||||
const SO_REUSEADDR = 2
|
const SO_REUSEADDR = 2
|
||||||
|
|
||||||
func net.listen[packed_host: i64, port: i64] : i64
|
func net.listen?[packed_host: i64, port: i64] : i64
|
||||||
|
err.clear()
|
||||||
let s: i64 = _builtin_syscall(SYS_socket, AF_INET, SOCK_STREAM, 0)
|
let s: i64 = _builtin_syscall(SYS_socket, AF_INET, SOCK_STREAM, 0)
|
||||||
if s < 0
|
if s < 0
|
||||||
|
err.set(ERR_SYSCALL_FAILED, "net.listen?: failed to create a socket")
|
||||||
return -1
|
return -1
|
||||||
|
|
||||||
let optval = 1
|
let optval = 1
|
||||||
if _builtin_syscall(SYS_setsockopt, s, SOL_SOCKET, SO_REUSEADDR, ^optval, 8) < 0
|
if _builtin_syscall(SYS_setsockopt, s, SOL_SOCKET, SO_REUSEADDR, ^optval, 8) < 0
|
||||||
_builtin_syscall(SYS_close, s)
|
_builtin_syscall(SYS_close, s)
|
||||||
|
err.set(ERR_SYSCALL_FAILED, "net.listen?: setsockopt() failed")
|
||||||
return -1
|
return -1
|
||||||
|
|
||||||
let sa: ptr = mem.alloc(16)
|
let sa: ptr = mem.alloc(16)
|
||||||
@@ -28,19 +31,23 @@ func net.listen[packed_host: i64, port: i64] : i64
|
|||||||
if _builtin_syscall(SYS_bind, s, sa, 16) < 0
|
if _builtin_syscall(SYS_bind, s, sa, 16) < 0
|
||||||
_builtin_syscall(SYS_close, s)
|
_builtin_syscall(SYS_close, s)
|
||||||
mem.free(sa)
|
mem.free(sa)
|
||||||
|
err.set(ERR_SYSCALL_FAILED, "net.listen?: failed to bind")
|
||||||
return -1
|
return -1
|
||||||
mem.free(sa)
|
mem.free(sa)
|
||||||
|
|
||||||
if _builtin_syscall(SYS_listen, s, 128) < 0
|
if _builtin_syscall(SYS_listen, s, 128) < 0
|
||||||
_builtin_syscall(SYS_close, s)
|
_builtin_syscall(SYS_close, s)
|
||||||
|
err.set(ERR_SYSCALL_FAILED, "net.listen?: listen() failed")
|
||||||
return -1
|
return -1
|
||||||
|
|
||||||
return s
|
return s
|
||||||
|
|
||||||
// TODO: resolve DNS
|
// TODO: resolve DNS
|
||||||
func net.connect[packed_host: i64, port: i64] : i64
|
func net.connect?[packed_host: i64, port: i64] : i64
|
||||||
|
err.clear()
|
||||||
let s: i64 = _builtin_syscall(SYS_socket, AF_INET, SOCK_STREAM, 0)
|
let s: i64 = _builtin_syscall(SYS_socket, AF_INET, SOCK_STREAM, 0)
|
||||||
if s < 0
|
if s < 0
|
||||||
|
err.set(ERR_SYSCALL_FAILED, "net.connect?: failed to create a socket")
|
||||||
return -1
|
return -1
|
||||||
|
|
||||||
let sa: ptr = mem.alloc(16)
|
let sa: ptr = mem.alloc(16)
|
||||||
@@ -57,6 +64,7 @@ func net.connect[packed_host: i64, port: i64] : i64
|
|||||||
if _builtin_syscall(SYS_connect, s, sa, 16) < 0
|
if _builtin_syscall(SYS_connect, s, sa, 16) < 0
|
||||||
mem.free(sa)
|
mem.free(sa)
|
||||||
_builtin_syscall(SYS_close, s)
|
_builtin_syscall(SYS_close, s)
|
||||||
|
err.set(ERR_CONNECTION_FAILED, "net.connect?: connection failed")
|
||||||
return -1
|
return -1
|
||||||
|
|
||||||
mem.free(sa)
|
mem.free(sa)
|
||||||
@@ -86,12 +94,14 @@ struct net.UDPPacket
|
|||||||
source_addr: ptr
|
source_addr: ptr
|
||||||
size: i64
|
size: i64
|
||||||
|
|
||||||
func net.create_udp_client[packed_host: i64, port: i64] : net.UDPSocket
|
func net.create_udp_client?[packed_host: i64, port: i64] : net.UDPSocket
|
||||||
|
err.clear()
|
||||||
let s: net.UDPSocket = new net.UDPSocket
|
let s: net.UDPSocket = new net.UDPSocket
|
||||||
|
|
||||||
s->fd = _builtin_syscall(SYS_socket, AF_INET, SOCK_DGRAM, 0)
|
s->fd = _builtin_syscall(SYS_socket, AF_INET, SOCK_DGRAM, 0)
|
||||||
if s->fd < 0
|
if s->fd < 0
|
||||||
mem.free(s)
|
mem.free(s)
|
||||||
|
err.set(ERR_SYSCALL_FAILED, "net.create_udp_client?: failed to create a socket")
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
s->addr = mem.alloc(16)
|
s->addr = mem.alloc(16)
|
||||||
@@ -106,13 +116,15 @@ func net.create_udp_client[packed_host: i64, port: i64] : net.UDPSocket
|
|||||||
s->addr[7] = packed_host & 255
|
s->addr[7] = packed_host & 255
|
||||||
return s
|
return s
|
||||||
|
|
||||||
func net.udp_listen[packed_host: i64, port: i64] : net.UDPSocket
|
func net.udp_listen?[packed_host: i64, port: i64] : net.UDPSocket
|
||||||
let s: net.UDPSocket = net.create_udp_client(packed_host, port)
|
err.clear()
|
||||||
if !s
|
let s: net.UDPSocket = net.create_udp_client?(packed_host, port)
|
||||||
|
if err.check()
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
if _builtin_syscall(SYS_bind, s->fd, s->addr, 16) < 0
|
if _builtin_syscall(SYS_bind, s->fd, s->addr, 16) < 0
|
||||||
net.UDPSocket.close_and_free(s)
|
net.UDPSocket.close_and_free(s)
|
||||||
|
err.set(ERR_SYSCALL_FAILED, "net.udp_listen?: failed to bind")
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
return s
|
return s
|
||||||
@@ -184,13 +196,15 @@ func net.build_dns_query[domain_name: str, record_type: i64] : io.Buffer
|
|||||||
io.Buffer.free(name)
|
io.Buffer.free(name)
|
||||||
return out
|
return out
|
||||||
|
|
||||||
func net.resolve[domain: str] : i64
|
// TODO: dont resolve IPs
|
||||||
|
func net.resolve?[domain: str] : i64
|
||||||
|
err.clear()
|
||||||
let query: io.Buffer = net.build_dns_query(domain, DNS_TYPE_A)
|
let query: io.Buffer = net.build_dns_query(domain, DNS_TYPE_A)
|
||||||
|
|
||||||
// TODO: this probably shouldnt be hardcoded
|
// TODO: this probably shouldnt be hardcoded
|
||||||
let s: net.UDPSocket = net.create_udp_client(net.pack_addr(8, 8, 8, 8), 53)
|
let s: net.UDPSocket = net.create_udp_client?(net.pack_addr(8, 8, 8, 8), 53)
|
||||||
if s == 0
|
if err.check()
|
||||||
return 0
|
return -1
|
||||||
|
|
||||||
net.udp_send_to(s, s->addr, query->data, query->size)
|
net.udp_send_to(s, s->addr, query->data, query->size)
|
||||||
io.Buffer.free(query)
|
io.Buffer.free(query)
|
||||||
|
|||||||
108
src/std/std.zr
108
src/std/std.zr
@@ -1,7 +1,37 @@
|
|||||||
|
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
|
||||||
|
|
||||||
|
func err.code[] : i64
|
||||||
|
return mem.read64(_builtin_err_code())
|
||||||
|
|
||||||
|
func err.msg[] : str
|
||||||
|
return mem.read64(_builtin_err_msg())
|
||||||
|
|
||||||
|
func err.check[] : bool
|
||||||
|
return err.code() != 0
|
||||||
|
|
||||||
|
func err.clear[] : void
|
||||||
|
err.set(0, 0)
|
||||||
|
|
||||||
|
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
|
func panic[msg: str] : void
|
||||||
io.print("PANIC: ")
|
io.print("PANIC: ")
|
||||||
io.println(msg)
|
io.println(msg)
|
||||||
(0 / 0) // crashes program which is kinda better since you get a gdb backtrace
|
// for gdb backtrace
|
||||||
|
_builtin_syscall(SYS_kill, os.getpid(), 6)
|
||||||
os.exit(1)
|
os.exit(1)
|
||||||
|
|
||||||
const MEM_BLOCK_SIZE = 32
|
const MEM_BLOCK_SIZE = 32
|
||||||
@@ -32,7 +62,8 @@ func mem._split_block[blk: mem.Block, needed: i64] : void
|
|||||||
blk->size = needed
|
blk->size = needed
|
||||||
blk->next = new_blk
|
blk->next = new_blk
|
||||||
|
|
||||||
func mem._request_space[size: i64] : mem.Block
|
func mem._request_space?[size: i64] : mem.Block
|
||||||
|
err.clear()
|
||||||
let needed: i64 = size + MEM_BLOCK_SIZE
|
let needed: i64 = size + MEM_BLOCK_SIZE
|
||||||
let alloc_size: i64 = (needed + 4095) & -4096
|
let alloc_size: i64 = (needed + 4095) & -4096
|
||||||
|
|
||||||
@@ -41,6 +72,7 @@ func mem._request_space[size: i64] : mem.Block
|
|||||||
// fd = -1, offset = 0
|
// fd = -1, offset = 0
|
||||||
let blk: mem.Block = _builtin_syscall(SYS_mmap, 0, alloc_size, 3, 34, -1, 0)
|
let blk: mem.Block = _builtin_syscall(SYS_mmap, 0, alloc_size, 3, 34, -1, 0)
|
||||||
if blk == -1
|
if blk == -1
|
||||||
|
err.set(ERR_ALLOC_FAILED, "mem._request_space: mmap failed")
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
blk->size = alloc_size - MEM_BLOCK_SIZE
|
blk->size = alloc_size - MEM_BLOCK_SIZE
|
||||||
@@ -56,7 +88,8 @@ func mem._request_space[size: i64] : mem.Block
|
|||||||
mem.write64(_builtin_heap_tail(), blk)
|
mem.write64(_builtin_heap_tail(), blk)
|
||||||
return blk
|
return blk
|
||||||
|
|
||||||
func mem.alloc[size: i64] : ptr
|
func mem.alloc?[size: i64] : ptr
|
||||||
|
err.clear()
|
||||||
if size == 0
|
if size == 0
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
@@ -70,8 +103,8 @@ func mem.alloc[size: i64] : ptr
|
|||||||
return cur + MEM_BLOCK_SIZE
|
return cur + MEM_BLOCK_SIZE
|
||||||
cur = cur->next
|
cur = cur->next
|
||||||
|
|
||||||
let blk: mem.Block = mem._request_space(size)
|
let blk: mem.Block = mem._request_space?(size)
|
||||||
if !blk
|
if err.check()
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
if !mem.read64(_builtin_heap_head())
|
if !mem.read64(_builtin_heap_head())
|
||||||
@@ -81,6 +114,9 @@ func mem.alloc[size: i64] : ptr
|
|||||||
|
|
||||||
return blk + MEM_BLOCK_SIZE
|
return blk + MEM_BLOCK_SIZE
|
||||||
|
|
||||||
|
func mem.alloc[size: i64] : ptr
|
||||||
|
return must(mem.alloc?(size))
|
||||||
|
|
||||||
func mem.free[x: ptr] : void
|
func mem.free[x: ptr] : void
|
||||||
if !x
|
if !x
|
||||||
return 0
|
return 0
|
||||||
@@ -127,9 +163,10 @@ func mem.free[x: ptr] : void
|
|||||||
mem.write64(_builtin_heap_tail(), blk->prev)
|
mem.write64(_builtin_heap_tail(), blk->prev)
|
||||||
_builtin_syscall(SYS_munmap, blk, block_total)
|
_builtin_syscall(SYS_munmap, blk, block_total)
|
||||||
|
|
||||||
func mem.realloc[x: ptr, new_size: i64] : ptr
|
func mem.realloc?[x: ptr, new_size: i64] : ptr
|
||||||
|
err.clear()
|
||||||
if !x
|
if !x
|
||||||
return mem.alloc(new_size)
|
return mem.alloc?(new_size)
|
||||||
|
|
||||||
if new_size == 0
|
if new_size == 0
|
||||||
mem.free(x)
|
mem.free(x)
|
||||||
@@ -159,11 +196,10 @@ func mem.realloc[x: ptr, new_size: i64] : ptr
|
|||||||
return x
|
return x
|
||||||
|
|
||||||
let new_ptr: ptr = mem.alloc(new_size)
|
let new_ptr: ptr = mem.alloc(new_size)
|
||||||
if !new_ptr
|
if err.check()
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
mem.copy(x, new_ptr, math.min(blk->size, new_size))
|
mem.copy(x, new_ptr, math.min(blk->size, new_size))
|
||||||
|
|
||||||
mem.free(x)
|
mem.free(x)
|
||||||
return new_ptr
|
return new_ptr
|
||||||
|
|
||||||
@@ -306,10 +342,12 @@ func io.Buffer.free[buf: io.Buffer] : void
|
|||||||
func io.file_exists[path: str] : bool
|
func io.file_exists[path: str] : bool
|
||||||
return _builtin_syscall(SYS_faccessat, -100, path, 0, 0) == 0
|
return _builtin_syscall(SYS_faccessat, -100, path, 0, 0) == 0
|
||||||
|
|
||||||
func io.read_file[path: str] : str
|
func io.read_file?[path: str] : str
|
||||||
|
err.clear()
|
||||||
let fd: i64 = _builtin_syscall(SYS_openat, -100, path, 0, 0)
|
let fd: i64 = _builtin_syscall(SYS_openat, -100, path, 0, 0)
|
||||||
if fd < 0
|
if fd < 0
|
||||||
panic("failed to open file") // TODO
|
err.set(ERR_OPEN_FAILED, "io.read_file?: failed to open file")
|
||||||
|
return 0
|
||||||
|
|
||||||
let size: i64 = _builtin_syscall(SYS_lseek, fd, 0, 2)
|
let size: i64 = _builtin_syscall(SYS_lseek, fd, 0, 2)
|
||||||
_builtin_syscall(SYS_lseek, fd, 0, 0)
|
_builtin_syscall(SYS_lseek, fd, 0, 0)
|
||||||
@@ -320,15 +358,18 @@ func io.read_file[path: str] : str
|
|||||||
|
|
||||||
if n < 0
|
if n < 0
|
||||||
mem.free(buffer)
|
mem.free(buffer)
|
||||||
panic("failed to read file") // TODO
|
err.set(ERR_READ_FAILED, "io.read_file?: failed to read file")
|
||||||
|
return 0
|
||||||
|
|
||||||
buffer[n] = 0
|
buffer[n] = 0
|
||||||
return buffer
|
return buffer
|
||||||
|
|
||||||
func io.read_binary_file[path: str] : io.Buffer
|
func io.read_binary_file?[path: str] : io.Buffer
|
||||||
|
err.clear()
|
||||||
let fd: i64 = _builtin_syscall(SYS_openat, -100, path, 0, 0)
|
let fd: i64 = _builtin_syscall(SYS_openat, -100, path, 0, 0)
|
||||||
if fd < 0
|
if fd < 0
|
||||||
panic("failed to open file") // TODO
|
err.set(ERR_OPEN_FAILED, "io.read_binary_file?: failed to open file")
|
||||||
|
return 0
|
||||||
|
|
||||||
let buffer: io.Buffer = new io.Buffer
|
let buffer: io.Buffer = new io.Buffer
|
||||||
buffer->size = _builtin_syscall(SYS_lseek, fd, 0, 2)
|
buffer->size = _builtin_syscall(SYS_lseek, fd, 0, 2)
|
||||||
@@ -340,22 +381,27 @@ func io.read_binary_file[path: str] : io.Buffer
|
|||||||
|
|
||||||
if n < 0
|
if n < 0
|
||||||
mem.free(buffer)
|
mem.free(buffer)
|
||||||
panic("failed to read file") // TODO
|
err.set(ERR_READ_FAILED, "io.read_binary_file?: failed to read file")
|
||||||
|
return 0
|
||||||
|
|
||||||
return buffer
|
return buffer
|
||||||
|
|
||||||
func io.write_file[path: str, content: str] : void
|
func io.write_file?[path: str, content: str] : void
|
||||||
|
err.clear()
|
||||||
let fd: i64 = _builtin_syscall(SYS_openat, -100, path, 0x241, 0o644)
|
let fd: i64 = _builtin_syscall(SYS_openat, -100, path, 0x241, 0o644)
|
||||||
if fd < 0
|
if fd < 0
|
||||||
panic("failed to open file") // TODO
|
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_write, fd, content, str.len(content))
|
||||||
_builtin_syscall(SYS_close, fd)
|
_builtin_syscall(SYS_close, fd)
|
||||||
|
|
||||||
func io.write_binary_file[path: str, content: ptr, size: i64] : void
|
func io.write_binary_file?[path: str, content: ptr, size: i64] : void
|
||||||
|
err.clear()
|
||||||
let fd: i64 = _builtin_syscall(SYS_openat, -100, path, 0x241, 0o644)
|
let fd: i64 = _builtin_syscall(SYS_openat, -100, path, 0x241, 0o644)
|
||||||
if fd < 0
|
if fd < 0
|
||||||
panic("failed to open file") // TODO
|
err.set(ERR_OPEN_FAILED, "io.write_binary_file?: failed to open file")
|
||||||
|
return 0
|
||||||
|
|
||||||
_builtin_syscall(SYS_write, fd, content, size)
|
_builtin_syscall(SYS_write, fd, content, size)
|
||||||
_builtin_syscall(SYS_close, fd)
|
_builtin_syscall(SYS_close, fd)
|
||||||
@@ -419,6 +465,9 @@ func str.find[haystack: str, needle: str] : i64
|
|||||||
|
|
||||||
if needle_len == 0
|
if needle_len == 0
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
if needle_len > haystack_len
|
||||||
|
return -1
|
||||||
|
|
||||||
for i in 0..(haystack_len - needle_len + 1)
|
for i in 0..(haystack_len - needle_len + 1)
|
||||||
let match: bool = true
|
let match: bool = true
|
||||||
@@ -695,7 +744,7 @@ func array.new[] : Array
|
|||||||
func array.new_with_size_zeroed[size: i64] : Array
|
func array.new_with_size_zeroed[size: i64] : Array
|
||||||
let xs: Array = new Array
|
let xs: Array = new Array
|
||||||
if size > 0
|
if size > 0
|
||||||
xs->data = mem.realloc(xs->data, size * 8)
|
xs->data = must(mem.realloc?(xs->data, size * 8))
|
||||||
mem.zero(xs->data, size * 8)
|
mem.zero(xs->data, size * 8)
|
||||||
xs->size = size
|
xs->size = size
|
||||||
xs->capacity = size
|
xs->capacity = size
|
||||||
@@ -716,7 +765,7 @@ func array.push[xs: Array, x: any] : void
|
|||||||
let new_capacity = 4
|
let new_capacity = 4
|
||||||
if xs->capacity != 0
|
if xs->capacity != 0
|
||||||
new_capacity = xs->capacity * 2
|
new_capacity = xs->capacity * 2
|
||||||
xs->data = mem.realloc(xs->data, new_capacity * 8)
|
xs->data = must(mem.realloc?(xs->data, new_capacity * 8))
|
||||||
xs->capacity = new_capacity
|
xs->capacity = new_capacity
|
||||||
|
|
||||||
mem.write64(xs->data + xs->size * 8, x)
|
mem.write64(xs->data + xs->size * 8, x)
|
||||||
@@ -819,19 +868,28 @@ func os.sleep[ms: i64] : void
|
|||||||
_builtin_syscall(SYS_nanosleep, req, 0)
|
_builtin_syscall(SYS_nanosleep, req, 0)
|
||||||
mem.free(req)
|
mem.free(req)
|
||||||
|
|
||||||
func os.urandom[n: i64]: ptr
|
func os.urandom?[n: i64]: ptr
|
||||||
|
err.clear()
|
||||||
let buffer: ptr = mem.alloc(n)
|
let buffer: ptr = mem.alloc(n)
|
||||||
|
if err.check()
|
||||||
|
return 0
|
||||||
|
|
||||||
let fd: i64 = _builtin_syscall(SYS_openat, -100, "/dev/urandom", 0, 0)
|
let fd: i64 = _builtin_syscall(SYS_openat, -100, "/dev/urandom", 0, 0)
|
||||||
|
if fd < 0
|
||||||
|
err.set(ERR_READ_FAILED, "os.urandom?: failed to open /dev/urandom")
|
||||||
|
return 0
|
||||||
|
|
||||||
let bytes_read: i64 = _builtin_syscall(SYS_read, fd, buffer, n)
|
let bytes_read: i64 = _builtin_syscall(SYS_read, fd, buffer, n)
|
||||||
_builtin_syscall(SYS_close, fd)
|
_builtin_syscall(SYS_close, fd)
|
||||||
|
|
||||||
if fd < 0 || n != bytes_read
|
if n != bytes_read
|
||||||
panic("failed to read /dev/urandom")
|
err.set(ERR_READ_FAILED, "os.urandom?: failed to read /dev/urandom")
|
||||||
|
return 0
|
||||||
|
|
||||||
return buffer
|
return buffer
|
||||||
|
|
||||||
func os.urandom_i64[]: i64
|
func os.urandom_i64[]: i64
|
||||||
let buffer: ptr = os.urandom(8)
|
let buffer: ptr = must(os.urandom?(8))
|
||||||
let n: i64 = mem.read64(buffer)
|
let n: i64 = mem.read64(buffer)
|
||||||
mem.free(buffer)
|
mem.free(buffer)
|
||||||
return n
|
return n
|
||||||
|
|||||||
@@ -346,7 +346,11 @@ impl Tokenizer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn scan_identifier(&mut self) -> Result<(), ZernError> {
|
fn scan_identifier(&mut self) -> Result<(), ZernError> {
|
||||||
while self.peek().is_alphanumeric() || self.peek() == '_' || self.peek() == '.' {
|
while self.peek().is_alphanumeric()
|
||||||
|
|| self.peek() == '_'
|
||||||
|
|| self.peek() == '.'
|
||||||
|
|| self.peek() == '?'
|
||||||
|
{
|
||||||
self.advance();
|
self.advance();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user