replace the horrible error system with multiple returns
This commit is contained in:
@@ -290,7 +290,9 @@ func main[argc: i64, argv: ptr] : i64
|
|||||||
|
|
||||||
c := chip8_create()
|
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
|
for i in 0..buffer->size
|
||||||
c->memory[0x200 + i] = buffer->data[i]
|
c->memory[0x200 + i] = buffer->data[i]
|
||||||
|
|||||||
@@ -26,9 +26,13 @@ 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)
|
||||||
|
|
||||||
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
|
// TODO: add string builder to std
|
||||||
req := "GET "
|
req := "GET "
|
||||||
|
|||||||
@@ -15,7 +15,11 @@ func part2[l1: Array, l2: Array] : void
|
|||||||
io.println_i64(out)
|
io.println_i64(out)
|
||||||
|
|
||||||
func main[] : i64
|
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 := []
|
l1 := []
|
||||||
l2 := []
|
l2 := []
|
||||||
|
|||||||
@@ -40,7 +40,11 @@ func part2[data: Array] : void
|
|||||||
io.println_i64(out)
|
io.println_i64(out)
|
||||||
|
|
||||||
func main[] : i64
|
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 := []
|
data := []
|
||||||
for i in 0..lines->size
|
for i in 0..lines->size
|
||||||
|
|||||||
@@ -56,7 +56,11 @@ func part2[lines: Array] : void
|
|||||||
io.println_i64(out)
|
io.println_i64(out)
|
||||||
|
|
||||||
func main[] : i64
|
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)
|
part1(lines)
|
||||||
part2(lines)
|
part2(lines)
|
||||||
|
|||||||
@@ -47,7 +47,11 @@ 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
|
||||||
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_left := []
|
||||||
rules_right := []
|
rules_right := []
|
||||||
|
|||||||
@@ -61,7 +61,11 @@ func part2[equations: Array] : void
|
|||||||
io.println_i64(out)
|
io.println_i64(out)
|
||||||
|
|
||||||
func main[] : i64
|
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 := []
|
equations := []
|
||||||
|
|
||||||
for i in 0..lines->size
|
for i in 0..lines->size
|
||||||
|
|||||||
@@ -47,7 +47,11 @@ func part2[lines: Array] : void
|
|||||||
io.println_i64(password)
|
io.println_i64(password)
|
||||||
|
|
||||||
func main[] : i64
|
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)
|
part1(lines)
|
||||||
part2(lines)
|
part2(lines)
|
||||||
|
|||||||
@@ -54,7 +54,11 @@ func part2[ranges: Array] : void
|
|||||||
io.println_i64(sum)
|
io.println_i64(sum)
|
||||||
|
|
||||||
func main[] : i64
|
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)
|
part1(ranges)
|
||||||
part2(ranges)
|
part2(ranges)
|
||||||
|
|||||||
@@ -45,7 +45,11 @@ func part2[lines: Array] : void
|
|||||||
io.println_i64(sum)
|
io.println_i64(sum)
|
||||||
|
|
||||||
func main[] : i64
|
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)
|
part1(lines)
|
||||||
part2(lines)
|
part2(lines)
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
func main[] : i64
|
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...")
|
io.println("Listening on port 8000...")
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
func main[] : i64
|
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...")
|
io.println("Listening on port 8000...")
|
||||||
while true
|
while true
|
||||||
|
|||||||
@@ -115,8 +115,6 @@ 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:
|
||||||
@@ -128,16 +126,6 @@ _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,18 +4,15 @@ 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, bool
|
||||||
err.clear()
|
|
||||||
s := _builtin_syscall(SYS_socket, AF_INET, SOCK_STREAM, 0)
|
s := _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, false
|
||||||
return -1
|
|
||||||
|
|
||||||
optval := 1
|
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, false
|
||||||
return -1
|
|
||||||
|
|
||||||
sa := mem.alloc(16)
|
sa := mem.alloc(16)
|
||||||
mem.zero(sa, 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
|
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, false
|
||||||
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, false
|
||||||
return -1
|
|
||||||
|
|
||||||
return s
|
return s, true
|
||||||
|
|
||||||
func net.connect?[packed_host: i64, port: i64] : i64
|
func net.connect[packed_host: i64, port: i64] : i64, bool
|
||||||
err.clear()
|
|
||||||
s := _builtin_syscall(SYS_socket, AF_INET, SOCK_STREAM, 0)
|
s := _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, false
|
||||||
return -1
|
|
||||||
|
|
||||||
sa := mem.alloc(16)
|
sa := mem.alloc(16)
|
||||||
mem.zero(sa, 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
|
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, false
|
||||||
return -1
|
|
||||||
|
|
||||||
mem.free(sa)
|
mem.free(sa)
|
||||||
return s
|
return s, true
|
||||||
|
|
||||||
func net.accept[s: i64, addr: ptr] : i64
|
func net.accept[s: i64, addr: ptr] : i64
|
||||||
addrlen := 16
|
addrlen := 16
|
||||||
@@ -89,15 +81,13 @@ struct net.UDPSocket
|
|||||||
fd: i64
|
fd: i64
|
||||||
addr: ptr
|
addr: ptr
|
||||||
|
|
||||||
func net.create_udp_client?[packed_host: i64, port: i64] : net.UDPSocket
|
func net.create_udp_client[packed_host: i64, port: i64] : net.UDPSocket, bool
|
||||||
err.clear()
|
|
||||||
s := new* net.UDPSocket
|
s := 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 as net.UDPSocket, false
|
||||||
return 0 as net.UDPSocket
|
|
||||||
|
|
||||||
s->addr = mem.alloc(16)
|
s->addr = mem.alloc(16)
|
||||||
mem.zero(s->addr, 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[5] = (packed_host >> 16) & 255
|
||||||
s->addr[6] = (packed_host >> 8) & 255
|
s->addr[6] = (packed_host >> 8) & 255
|
||||||
s->addr[7] = packed_host & 255
|
s->addr[7] = packed_host & 255
|
||||||
return s
|
return s, true
|
||||||
|
|
||||||
func net.create_udp_server?[packed_host: i64, port: i64] : net.UDPSocket
|
func net.create_udp_server[packed_host: i64, port: i64] : net.UDPSocket, bool
|
||||||
err.clear()
|
~s, ok := net.create_udp_client(packed_host, port)
|
||||||
s := net.create_udp_client?(packed_host, port)
|
if !ok
|
||||||
if err.check()
|
return 0 as net.UDPSocket, false
|
||||||
return 0 as net.UDPSocket
|
|
||||||
|
|
||||||
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.create_udp_server?: failed to bind")
|
return 0 as net.UDPSocket, false
|
||||||
return 0 as net.UDPSocket
|
|
||||||
|
|
||||||
return s
|
return s, true
|
||||||
|
|
||||||
func net.udp_send_to[s: net.UDPSocket, addr: ptr, data: ptr, size: i64] : void
|
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)
|
_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
|
func net.encode_dns_name[domain: str] : Blob
|
||||||
domain_len := str.len(domain)
|
domain_len := str.len(domain)
|
||||||
buf : Blob = must(Blob.alloc?(domain_len + 2))
|
buf := Blob.alloc(domain_len + 2)
|
||||||
out_pos := 0
|
out_pos := 0
|
||||||
part_start := 0
|
part_start := 0
|
||||||
i := 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
|
func net.build_dns_query[domain_name: str, record_type: i64] : Blob
|
||||||
name := net.encode_dns_name(domain_name)
|
name := net.encode_dns_name(domain_name)
|
||||||
out : Blob = must(Blob.alloc?(12 + name->size + 4))
|
out := Blob.alloc(12 + name->size + 4)
|
||||||
|
|
||||||
// header
|
// header
|
||||||
id := math.abs(os.urandom_i64() % 65536)
|
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
|
return out
|
||||||
|
|
||||||
// TODO: dont resolve if its already an IP
|
// TODO: dont resolve if its already an IP
|
||||||
func net.resolve?[domain: str] : i64
|
func net.resolve[domain: str] : i64, bool
|
||||||
err.clear()
|
|
||||||
query := net.build_dns_query(domain, DNS_TYPE_A)
|
query := net.build_dns_query(domain, DNS_TYPE_A)
|
||||||
|
|
||||||
// TODO: this probably shouldnt be hardcoded
|
// TODO: this probably shouldnt be hardcoded
|
||||||
s := net.create_udp_client?(net.pack_addr(1, 1, 1, 1), 53)
|
~s, ok := net.create_udp_client(net.pack_addr(1, 1, 1, 1), 53)
|
||||||
if err.check()
|
if !ok
|
||||||
return -1
|
return -1, false
|
||||||
|
|
||||||
net.udp_send_to(s, s->addr, query->data, query->size)
|
net.udp_send_to(s, s->addr, query->data, query->size)
|
||||||
Blob.free(query)
|
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)
|
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)
|
net.UDPPacket.free(pkt)
|
||||||
return out
|
return out, true
|
||||||
|
|||||||
170
src/std/std.zr
170
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
|
func panic[msg: str] : void
|
||||||
io.print("PANIC: ")
|
io.print("PANIC: ")
|
||||||
io.println(msg)
|
io.println(msg)
|
||||||
@@ -62,8 +32,7 @@ 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()
|
|
||||||
needed := size + MEM_BLOCK_SIZE
|
needed := size + MEM_BLOCK_SIZE
|
||||||
alloc_size := (needed + 4095) & -4096
|
alloc_size := (needed + 4095) & -4096
|
||||||
|
|
||||||
@@ -72,8 +41,7 @@ func mem._request_space?[size: i64] : mem.Block
|
|||||||
// fd = -1, offset = 0
|
// fd = -1, offset = 0
|
||||||
blk := _builtin_syscall(SYS_mmap, 0, alloc_size, 3, 34, -1, 0) as mem.Block
|
blk := _builtin_syscall(SYS_mmap, 0, alloc_size, 3, 34, -1, 0) as mem.Block
|
||||||
if (blk as ptr as i64) == -1
|
if (blk as ptr as i64) == -1
|
||||||
err.set(ERR_ALLOC_FAILED, "mem._request_space: mmap failed")
|
panic("mem._request_space: failed to mmap")
|
||||||
return 0 as mem.Block
|
|
||||||
|
|
||||||
blk->size = alloc_size - MEM_BLOCK_SIZE
|
blk->size = alloc_size - MEM_BLOCK_SIZE
|
||||||
blk->free = false
|
blk->free = false
|
||||||
@@ -88,11 +56,9 @@ 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
|
||||||
err.set(ERR_ALLOC_FAILED, "mem.alloc? called with non-positive size")
|
panic("mem.alloc: called with nonpositive size")
|
||||||
return 0 as ptr
|
|
||||||
|
|
||||||
size = mem._align(size)
|
size = mem._align(size)
|
||||||
|
|
||||||
@@ -104,9 +70,7 @@ func mem.alloc?[size: i64] : ptr
|
|||||||
return cur as ptr + MEM_BLOCK_SIZE
|
return cur as ptr + MEM_BLOCK_SIZE
|
||||||
cur = cur->next
|
cur = cur->next
|
||||||
|
|
||||||
blk := mem._request_space?(size)
|
blk := mem._request_space(size)
|
||||||
if err.check()
|
|
||||||
return 0 as ptr
|
|
||||||
|
|
||||||
if !mem.read64(_builtin_heap_head())
|
if !mem.read64(_builtin_heap_head())
|
||||||
mem.write64(_builtin_heap_head(), blk)
|
mem.write64(_builtin_heap_head(), blk)
|
||||||
@@ -115,9 +79,6 @@ func mem.alloc?[size: i64] : ptr
|
|||||||
|
|
||||||
return blk as ptr + MEM_BLOCK_SIZE
|
return blk as ptr + MEM_BLOCK_SIZE
|
||||||
|
|
||||||
func mem.alloc[size: i64] : ptr
|
|
||||||
return must(mem.alloc?(size))
|
|
||||||
|
|
||||||
func mem.free[x: any] : void
|
func mem.free[x: any] : void
|
||||||
if x == 0
|
if x == 0
|
||||||
return 0
|
return 0
|
||||||
@@ -163,14 +124,12 @@ func mem.free[x: any] : 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
|
||||||
err.set(ERR_ALLOC_FAILED, "mem.realloc? called with negative size")
|
panic("mem.realloc: called with negative new_size")
|
||||||
return 0 as ptr
|
|
||||||
|
|
||||||
if new_size == 0
|
if new_size == 0
|
||||||
mem.free(x)
|
mem.free(x)
|
||||||
@@ -198,9 +157,7 @@ func mem.realloc?[x: ptr, new_size: i64] : ptr
|
|||||||
mem._split_block(blk, new_size)
|
mem._split_block(blk, new_size)
|
||||||
return x
|
return x
|
||||||
|
|
||||||
new_ptr := mem.alloc?(new_size)
|
new_ptr := mem.alloc(new_size)
|
||||||
if err.check()
|
|
||||||
return 0 as ptr
|
|
||||||
|
|
||||||
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)
|
||||||
@@ -333,21 +290,17 @@ func io.read_line[]: str
|
|||||||
if n < 0
|
if n < 0
|
||||||
n = 0
|
n = 0
|
||||||
buffer[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
|
return buffer
|
||||||
|
|
||||||
struct Blob
|
struct Blob
|
||||||
data: ptr
|
data: ptr
|
||||||
size: i64
|
size: i64
|
||||||
|
|
||||||
func Blob.alloc?[size: i64] : Blob
|
func Blob.alloc[size: i64] : Blob
|
||||||
err.clear()
|
|
||||||
buffer := new* Blob
|
buffer := new* Blob
|
||||||
buffer->size = size
|
buffer->size = size
|
||||||
buffer->data = mem.alloc?(size)
|
buffer->data = mem.alloc(size)
|
||||||
if err.check()
|
|
||||||
mem.free(buffer)
|
|
||||||
return 0 as Blob
|
|
||||||
return buffer
|
return buffer
|
||||||
|
|
||||||
func Blob.free[buf: Blob] : void
|
func Blob.free[buf: Blob] : void
|
||||||
@@ -373,74 +326,58 @@ func io.is_a_directory[path: str] : bool
|
|||||||
mem.free(st)
|
mem.free(st)
|
||||||
return out
|
return out
|
||||||
|
|
||||||
func io.read_text_file?[path: str] : str
|
func io.read_text_file[path: str] : str, bool
|
||||||
err.clear()
|
|
||||||
fd := _builtin_syscall(SYS_openat, -100, path, 0, 0)
|
fd := _builtin_syscall(SYS_openat, -100, path, 0, 0)
|
||||||
if fd < 0
|
if fd < 0
|
||||||
err.set(ERR_OPEN_FAILED, "io.read_text_file?: failed to open file")
|
return 0 as str, false
|
||||||
return 0 as str
|
|
||||||
|
|
||||||
size := _builtin_syscall(SYS_lseek, fd, 0, 2)
|
size := _builtin_syscall(SYS_lseek, fd, 0, 2)
|
||||||
_builtin_syscall(SYS_lseek, fd, 0, 0)
|
_builtin_syscall(SYS_lseek, fd, 0, 0)
|
||||||
|
|
||||||
buffer := mem.alloc?(size + 1) as str
|
buffer := mem.alloc(size + 1)
|
||||||
if err.check()
|
|
||||||
_builtin_syscall(SYS_close, fd)
|
|
||||||
return 0 as str
|
|
||||||
|
|
||||||
n := _builtin_syscall(SYS_read, fd, buffer, size)
|
n := _builtin_syscall(SYS_read, fd, buffer, size)
|
||||||
_builtin_syscall(SYS_close, fd)
|
_builtin_syscall(SYS_close, fd)
|
||||||
|
|
||||||
if n != size
|
if n != size
|
||||||
mem.free(buffer)
|
mem.free(buffer)
|
||||||
err.set(ERR_READ_FAILED, "io.read_text_file?: failed to read file")
|
return 0 as str, false
|
||||||
return 0 as str
|
|
||||||
|
|
||||||
buffer[n] = 0
|
buffer[n] = 0
|
||||||
return buffer
|
return buffer as str, true
|
||||||
|
|
||||||
func io.read_binary_file?[path: str] : Blob
|
func io.read_binary_file[path: str] : Blob, bool
|
||||||
err.clear()
|
|
||||||
fd := _builtin_syscall(SYS_openat, -100, path, 0, 0)
|
fd := _builtin_syscall(SYS_openat, -100, path, 0, 0)
|
||||||
if fd < 0
|
if fd < 0
|
||||||
err.set(ERR_OPEN_FAILED, "io.read_binary_file?: failed to open file")
|
return 0 as Blob, false
|
||||||
return 0 as Blob
|
|
||||||
|
|
||||||
buf := new* Blob
|
buf := new* Blob
|
||||||
buf->size = _builtin_syscall(SYS_lseek, fd, 0, 2)
|
buf->size = _builtin_syscall(SYS_lseek, fd, 0, 2)
|
||||||
_builtin_syscall(SYS_lseek, fd, 0, 0)
|
_builtin_syscall(SYS_lseek, fd, 0, 0)
|
||||||
|
|
||||||
buf->data = mem.alloc?(buf->size)
|
buf->data = mem.alloc(buf->size)
|
||||||
if err.check()
|
|
||||||
Blob.free(buf)
|
|
||||||
_builtin_syscall(SYS_close, fd)
|
|
||||||
return 0 as Blob
|
|
||||||
|
|
||||||
n := _builtin_syscall(SYS_read, fd, buf->data, buf->size)
|
n := _builtin_syscall(SYS_read, fd, buf->data, buf->size)
|
||||||
_builtin_syscall(SYS_close, fd)
|
_builtin_syscall(SYS_close, fd)
|
||||||
|
|
||||||
if n != buf->size
|
if n != buf->size
|
||||||
Blob.free(buf)
|
Blob.free(buf)
|
||||||
err.set(ERR_READ_FAILED, "io.read_binary_file?: failed to read file")
|
return 0 as Blob, false
|
||||||
return 0 as Blob
|
|
||||||
|
|
||||||
return buf
|
return buf, true
|
||||||
|
|
||||||
func io.write_file?[path: str, content: str] : void
|
func io.write_file[path: str, content: str] : bool
|
||||||
io.write_binary_file?(path, content as ptr, str.len(content))
|
return io.write_binary_file(path, content as ptr, str.len(content))
|
||||||
|
|
||||||
func io.write_binary_file?[path: str, content: ptr, size: i64] : void
|
func io.write_binary_file[path: str, content: ptr, size: i64] : bool
|
||||||
err.clear()
|
|
||||||
fd := _builtin_syscall(SYS_openat, -100, path, 0x241, 0o644)
|
fd := _builtin_syscall(SYS_openat, -100, path, 0x241, 0o644)
|
||||||
if fd < 0
|
if fd < 0
|
||||||
err.set(ERR_OPEN_FAILED, "io.write_binary_file?: failed to open file")
|
return false
|
||||||
return 0
|
|
||||||
|
|
||||||
n := _builtin_syscall(SYS_write, fd, content, size)
|
n := _builtin_syscall(SYS_write, fd, content, size)
|
||||||
_builtin_syscall(SYS_close, fd)
|
_builtin_syscall(SYS_close, fd)
|
||||||
if n != size
|
if n != size
|
||||||
err.set(ERR_WRITE_FAILED, "io.write_binary_file?: failed to write file")
|
return false
|
||||||
return 0
|
return true
|
||||||
|
|
||||||
func str.len[s: str] : i64
|
func str.len[s: str] : i64
|
||||||
i := 0
|
i := 0
|
||||||
@@ -785,7 +722,7 @@ func array.new[] : Array
|
|||||||
func array.new_preallocated_and_zeroed[size: i64] : Array
|
func array.new_preallocated_and_zeroed[size: i64] : Array
|
||||||
xs := new* Array
|
xs := new* Array
|
||||||
if size > 0
|
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)
|
mem.zero(xs->data, size * 8)
|
||||||
xs->size = size
|
xs->size = size
|
||||||
xs->capacity = size
|
xs->capacity = size
|
||||||
@@ -806,7 +743,7 @@ func array.push[xs: Array, x: any] : void
|
|||||||
new_capacity := 4
|
new_capacity := 4
|
||||||
if xs->capacity != 0
|
if xs->capacity != 0
|
||||||
new_capacity = xs->capacity * 2
|
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
|
xs->capacity = new_capacity
|
||||||
|
|
||||||
mem.write64(xs->data + xs->size * 8, x)
|
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)
|
new_node->next = array.nth(map->table, index)
|
||||||
array.set(map->table, index, new_node)
|
array.set(map->table, index, new_node)
|
||||||
|
|
||||||
func HashMap.get?[map: HashMap, key: str] : any
|
func HashMap.get[map: HashMap, key: str] : any, bool
|
||||||
err.clear()
|
|
||||||
index := HashMap._djb2(key)
|
index := HashMap._djb2(key)
|
||||||
current : HashMap._Node = array.nth(map->table, index)
|
current : HashMap._Node = array.nth(map->table, index)
|
||||||
|
|
||||||
while current as ptr
|
while current as ptr
|
||||||
if str.equal(current->key, key)
|
if str.equal(current->key, key)
|
||||||
return current->value
|
return current->value, true
|
||||||
current = current->next
|
current = current->next
|
||||||
|
|
||||||
err.set(ERR_KEY_ERROR, "key not found")
|
return 0 as any, false
|
||||||
return 0
|
|
||||||
|
|
||||||
func HashMap.delete[map: HashMap, key: str] : void
|
func HashMap.delete[map: HashMap, key: str] : void
|
||||||
index := HashMap._djb2(key)
|
index := HashMap._djb2(key)
|
||||||
@@ -990,30 +925,23 @@ func os.sleep[ms: i64] : void
|
|||||||
req->tv_nsec = (ms % 1000) * 1000000
|
req->tv_nsec = (ms % 1000) * 1000000
|
||||||
_builtin_syscall(SYS_nanosleep, req, 0)
|
_builtin_syscall(SYS_nanosleep, req, 0)
|
||||||
|
|
||||||
func os.urandom?[n: i64]: ptr
|
func os.urandom[n: i64]: ptr
|
||||||
err.clear()
|
|
||||||
buffer := mem.alloc(n)
|
buffer := mem.alloc(n)
|
||||||
if err.check()
|
|
||||||
return 0 as ptr
|
|
||||||
|
|
||||||
fd := _builtin_syscall(SYS_openat, -100, "/dev/urandom", 0, 0)
|
fd := _builtin_syscall(SYS_openat, -100, "/dev/urandom", 0, 0)
|
||||||
if fd < 0
|
if fd < 0
|
||||||
mem.free(buffer)
|
panic("os.urandom: failed to open /dev/urandom")
|
||||||
err.set(ERR_OPEN_FAILED, "os.urandom?: failed to open /dev/urandom")
|
|
||||||
return 0 as ptr
|
|
||||||
|
|
||||||
bytes_read := _builtin_syscall(SYS_read, fd, buffer, n)
|
bytes_read := _builtin_syscall(SYS_read, fd, buffer, n)
|
||||||
_builtin_syscall(SYS_close, fd)
|
_builtin_syscall(SYS_close, fd)
|
||||||
|
|
||||||
if n != bytes_read
|
if n != bytes_read
|
||||||
mem.free(buffer)
|
panic("os.urandom: failed to read /dev/urandom")
|
||||||
err.set(ERR_READ_FAILED, "os.urandom?: failed to read /dev/urandom")
|
|
||||||
return 0 as ptr
|
|
||||||
|
|
||||||
return buffer
|
return buffer
|
||||||
|
|
||||||
func os.urandom_i64[]: i64
|
func os.urandom_i64[]: i64
|
||||||
buffer : ptr = must(os.urandom?(8))
|
buffer := os.urandom(8)
|
||||||
n := mem.read64(buffer)
|
n := mem.read64(buffer)
|
||||||
mem.free(buffer)
|
mem.free(buffer)
|
||||||
return n
|
return n
|
||||||
@@ -1029,12 +957,10 @@ func os.time[] : i64
|
|||||||
return out
|
return out
|
||||||
|
|
||||||
// voodoo magic
|
// voodoo magic
|
||||||
func os.run_shell_command?[command: str] : i64
|
func os.run_shell_command[command: str] : i64, bool
|
||||||
err.clear()
|
|
||||||
pid := _builtin_syscall(SYS_fork)
|
pid := _builtin_syscall(SYS_fork)
|
||||||
if pid < 0
|
if pid < 0
|
||||||
err.set(ERR_SYSCALL_FAILED, "os.run_shell_command?: failed to fork")
|
return -1, false
|
||||||
return -1
|
|
||||||
|
|
||||||
if pid == 0
|
if pid == 0
|
||||||
argv := ["sh", "-c", command, 0] // gets freed after child process exits
|
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
|
status := 0
|
||||||
wp := _builtin_syscall(SYS_wait4, pid, ^status, 0, 0)
|
wp := _builtin_syscall(SYS_wait4, pid, ^status, 0, 0)
|
||||||
if wp < 0
|
if wp < 0
|
||||||
err.set(ERR_SYSCALL_FAILED, "os.run_shell_command?: wait() failed")
|
return -1, false
|
||||||
return -1
|
|
||||||
st := status & 0xffffffff
|
st := status & 0xffffffff
|
||||||
|
|
||||||
if (st & 0x7f) == 0
|
if (st & 0x7f) == 0
|
||||||
return (st >> 8) & 0xff
|
return (st >> 8) & 0xff, true
|
||||||
else
|
else
|
||||||
return -(st & 0x7f)
|
return -(st & 0x7f), true
|
||||||
|
|
||||||
func os.list_directory?[path: str] : Array
|
func os.list_directory[path: str] : Array, bool
|
||||||
err.clear()
|
|
||||||
fd := _builtin_syscall(SYS_openat, -100, path, 0, 0)
|
fd := _builtin_syscall(SYS_openat, -100, path, 0, 0)
|
||||||
if fd < 0
|
if fd < 0
|
||||||
err.set(ERR_OPEN_FAILED, "os.list_directory?: failed to open dir")
|
return 0 as Array, false
|
||||||
return 0 as Array
|
|
||||||
|
|
||||||
files := []
|
files := []
|
||||||
buf := mem.alloc(1024)
|
buf := mem.alloc(1024)
|
||||||
@@ -1072,8 +995,7 @@ func os.list_directory?[path: str] : Array
|
|||||||
array.free(files)
|
array.free(files)
|
||||||
|
|
||||||
_builtin_syscall(SYS_close, fd)
|
_builtin_syscall(SYS_close, fd)
|
||||||
err.set(ERR_SYSCALL_FAILED, "os.list_directory?: getdents64() failed")
|
return 0 as Array, false
|
||||||
return 0 as Array
|
|
||||||
else if n == 0
|
else if n == 0
|
||||||
break
|
break
|
||||||
|
|
||||||
@@ -1096,4 +1018,4 @@ func os.list_directory?[path: str] : Array
|
|||||||
|
|
||||||
mem.free(buf)
|
mem.free(buf)
|
||||||
_builtin_syscall(SYS_close, fd)
|
_builtin_syscall(SYS_close, fd)
|
||||||
return files
|
return files, true
|
||||||
|
|||||||
@@ -46,8 +46,6 @@ impl SymbolTable {
|
|||||||
functions: HashMap::from([
|
functions: HashMap::from([
|
||||||
("_builtin_heap_head".into(), FnType::new("ptr", vec![])),
|
("_builtin_heap_head".into(), FnType::new("ptr", vec![])),
|
||||||
("_builtin_heap_tail".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_read64".into(), FnType::new("i64", vec!["ptr"])),
|
||||||
(
|
(
|
||||||
"_builtin_set64".into(),
|
"_builtin_set64".into(),
|
||||||
|
|||||||
@@ -348,11 +348,7 @@ impl Tokenizer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn scan_identifier(&mut self) -> Result<(), ZernError> {
|
fn scan_identifier(&mut self) -> Result<(), ZernError> {
|
||||||
while self.peek().is_alphanumeric()
|
while self.peek().is_alphanumeric() || self.peek() == '_' || self.peek() == '.' {
|
||||||
|| self.peek() == '_'
|
|
||||||
|| self.peek() == '.'
|
|
||||||
|| self.peek() == '?'
|
|
||||||
{
|
|
||||||
self.advance();
|
self.advance();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
14
test.zr
14
test.zr
@@ -10,7 +10,8 @@ func run_test[x: str] : void
|
|||||||
io.printf("Building %s...\n", x)
|
io.printf("Building %s...\n", x)
|
||||||
|
|
||||||
build_start_time := os.time()
|
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)
|
os.exit(1)
|
||||||
build_end_time := os.time()
|
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_cmd = str.concat(run_cmd, " http://example.com")
|
||||||
|
|
||||||
run_start_time := os.time()
|
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)
|
os.exit(1)
|
||||||
run_end_time := os.time()
|
run_end_time := os.time()
|
||||||
|
|
||||||
io.printf("Running %s took %dms\n", x, run_end_time - run_start_time)
|
io.printf("Running %s took %dms\n", x, run_end_time - run_start_time)
|
||||||
|
|
||||||
func run_directory[dir: str] : void
|
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
|
for i in 0..files->size
|
||||||
run_test(str.concat(dir, array.nth(files, i)))
|
run_test(str.concat(dir, array.nth(files, i)))
|
||||||
|
|
||||||
array.free(files)
|
array.free(files)
|
||||||
|
|
||||||
func main[] : i64
|
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/")
|
||||||
run_directory("examples/puzzles/")
|
run_directory("examples/puzzles/")
|
||||||
|
|||||||
Reference in New Issue
Block a user