From a9bd4fe9f9279b9ed2eea321f7aca40c75f6c23f Mon Sep 17 00:00:00 2001 From: Toni Date: Sun, 7 Jun 2026 09:33:26 +0200 Subject: [PATCH] string hosts in net.* --- examples/chip8.zr | 2 +- examples/curl.zr | 6 +- examples/puzzles/aoc2024_01.zr | 1 - examples/tcp_server.zr | 2 +- examples/udp_server.zr | 2 +- src/codegen_x86_64.rs | 32 +++++----- src/std/net.zr | 112 ++++++++++++++++++++++----------- src/std/std.zr | 23 ++++--- 8 files changed, 109 insertions(+), 71 deletions(-) diff --git a/examples/chip8.zr b/examples/chip8.zr index 9770073..da61804 100644 --- a/examples/chip8.zr +++ b/examples/chip8.zr @@ -49,7 +49,7 @@ func CHIP8.free[c: CHIP8] : void c->keyboard->free() c->display->free() c->keyboard_map->free() - (c as ptr)->free() + mem.free(c) func CHIP8.disassemble[c: CHIP8, ins_count: i64] : void for i in 0..ins_count diff --git a/examples/curl.zr b/examples/curl.zr index 1199166..68f474e 100644 --- a/examples/curl.zr +++ b/examples/curl.zr @@ -26,11 +26,7 @@ func main[argc: i64, argv: ptr] : i64 if i < url_len path = url->substr(i, url_len - i) - ~addr, ok := net.resolve(host) - if !ok - panic("failed to resolve host") - - ~s, ok := net.connect(addr, 80) + ~s, ok := net.connect(host, 80) if !ok panic("failed to connect") diff --git a/examples/puzzles/aoc2024_01.zr b/examples/puzzles/aoc2024_01.zr index 8fed0b2..180a7e1 100644 --- a/examples/puzzles/aoc2024_01.zr +++ b/examples/puzzles/aoc2024_01.zr @@ -26,7 +26,6 @@ func main[] : i64 for i in 0..lines->size line : str = lines->nth(i) - parts := line->split(" ") l1->push((parts->nth(0) as str)->parse_i64()) diff --git a/examples/tcp_server.zr b/examples/tcp_server.zr index 4a6d368..461384a 100644 --- a/examples/tcp_server.zr +++ b/examples/tcp_server.zr @@ -1,5 +1,5 @@ func main[] : i64 - ~s, ok := net.listen(net.pack_addr(127, 0, 0, 1), 8000) + ~s, ok := net.listen("127.0.0.1", 8000) if !ok panic("failed to listen") diff --git a/examples/udp_server.zr b/examples/udp_server.zr index e160cf2..c5f721f 100644 --- a/examples/udp_server.zr +++ b/examples/udp_server.zr @@ -1,5 +1,5 @@ func main[] : i64 - ~s, ok := net.create_udp_server(net.pack_addr(127, 0, 0, 1), 8000) + ~s, ok := net.create_udp_server("127.0.0.1", 8000) if !ok panic("net.create_udp_server failed") diff --git a/src/codegen_x86_64.rs b/src/codegen_x86_64.rs index fd1b8d9..a92935e 100644 --- a/src/codegen_x86_64.rs +++ b/src/codegen_x86_64.rs @@ -670,7 +670,11 @@ _builtin_environ: self.emit_call_setup(arg_count); if let ExprKind::Variable(callee_name) = &callee.kind { - if self.symbol_table.functions.contains_key(&callee_name.lexeme) { + if self + .symbol_table + .functions + .contains_key(&callee_name.lexeme) + { // its a function (defined/builtin/extern) emit!(&mut self.output, " call {}", callee_name.lexeme); } else { @@ -852,28 +856,28 @@ _builtin_environ: fn emit_var_arg(&mut self, env: &mut Env, index_expr: &Expr) -> Result<(), ZernError> { self.compile_expr(env, index_expr)?; - emit!(&mut self.output, " mov r10, rax"); + emit!(&mut self.output, " mov r10, rax"); let stack_label = self.label(); let done_label = self.label(); - emit!(&mut self.output, " cmp r10, 6"); - emit!(&mut self.output, " jge {}", stack_label); + emit!(&mut self.output, " cmp r10, 6"); + emit!(&mut self.output, " jge {}", stack_label); // < 6 - emit!(&mut self.output, " mov rax, r10"); - emit!(&mut self.output, " inc rax"); - emit!(&mut self.output, " shl rax, 3"); - emit!(&mut self.output, " neg rax"); - emit!(&mut self.output, " mov rax, [rbp + rax]"); - emit!(&mut self.output, " jmp {}", done_label); + emit!(&mut self.output, " mov rax, r10"); + emit!(&mut self.output, " inc rax"); + emit!(&mut self.output, " shl rax, 3"); + emit!(&mut self.output, " neg rax"); + emit!(&mut self.output, " mov rax, [rbp + rax]"); + emit!(&mut self.output, " jmp {}", done_label); // >= 6 emit!(&mut self.output, "{}:", stack_label); - emit!(&mut self.output, " mov rax, r10"); - emit!(&mut self.output, " sub rax, 6"); - emit!(&mut self.output, " shl rax, 3"); - emit!(&mut self.output, " mov rax, [rbp + 16 + rax]"); + emit!(&mut self.output, " mov rax, r10"); + emit!(&mut self.output, " sub rax, 6"); + emit!(&mut self.output, " shl rax, 3"); + emit!(&mut self.output, " mov rax, [rbp + 16 + rax]"); emit!(&mut self.output, "{}:", done_label); Ok(()) diff --git a/src/std/net.zr b/src/std/net.zr index 0305470..582cf07 100644 --- a/src/std/net.zr +++ b/src/std/net.zr @@ -10,7 +10,7 @@ const DNS_TYPE_A = 1 const DNS_CLASS_IN = 1 const DNS_RECURSION_DESIRED = 256 -func net.listen[packed_host: i64, port: i64] : i64, bool +func net.listen[host: str, port: i64] : i64, bool s := _builtin_syscall(SYS_socket, AF_INET, SOCK_STREAM, 0) if s < 0 return -1, false @@ -19,6 +19,10 @@ func net.listen[packed_host: i64, port: i64] : i64, bool if _builtin_syscall(SYS_setsockopt, s, SOL_SOCKET, SO_REUSEADDR, ^optval, 8) < 0 _builtin_syscall(SYS_close, s) return -1, false + + ~packed_host, ok := net.resolve(host) + if !ok + return -1, false sa := _stackalloc(16) net._build_sa(sa, packed_host, port) @@ -33,10 +37,14 @@ func net.listen[packed_host: i64, port: i64] : i64, bool return s, true -func net.connect[packed_host: i64, port: i64] : i64, bool +func net.connect[host: str, port: i64] : i64, bool s := _builtin_syscall(SYS_socket, AF_INET, SOCK_STREAM, 0) if s < 0 return -1, false + + ~packed_host, ok := net.resolve(host) + if !ok + return -1, false sa := _stackalloc(16) net._build_sa(sa, packed_host, port) @@ -91,22 +99,26 @@ func net.UDPSocket.receive[s: net.UDPSocket, size: i64] : net.UDPPacket func net.UDPSocket.close_and_free[s: net.UDPSocket] : void _builtin_syscall(SYS_close, s->fd) s->addr->free() - (s as ptr)->free() + mem.free(s) -func net.create_udp_client[packed_host: i64, port: i64] : net.UDPSocket, bool +func net.create_udp_client[host: str, port: i64] : net.UDPSocket, bool s := new* net.UDPSocket + ~packed_host, ok := net.resolve(host) + if !ok + return 0 as net.UDPSocket, false + s->fd = _builtin_syscall(SYS_socket, AF_INET, SOCK_DGRAM, 0) if s->fd < 0 - s->close_and_free() + mem.free(s) return 0 as net.UDPSocket, false s->addr = mem.alloc(16) net._build_sa(s->addr, packed_host, port) return s, true -func net.create_udp_server[packed_host: i64, port: i64] : net.UDPSocket, bool - ~s, ok := net.create_udp_client(packed_host, port) +func net.create_udp_server[host: str, port: i64] : net.UDPSocket, bool + ~s, ok := net.create_udp_client(host, port) if !ok return 0 as net.UDPSocket, false @@ -127,7 +139,61 @@ struct net.UDPPacket func net.UDPPacket.free[pkt: net.UDPPacket] : void pkt->data->free() pkt->source_addr->free() - (pkt as ptr)->free() + mem.free(pkt) + +func net.resolve[domain: str] : i64, bool + // if domain is already an ip, skip dns resolution + parts := domain->split(".") + if parts->size == 4 + valid := true + for i in 0..4 + p := parts->nth(i) as str + if p->len() < 1 || p->len() > 3 + valid = false + break + for j in 0..p->len() + if !p[j]->is_digit() + valid = false + break + if !valid + break + if valid + a := (parts->nth(0) as str)->parse_i64() + b := (parts->nth(1) as str)->parse_i64() + c := (parts->nth(2) as str)->parse_i64() + d := (parts->nth(3) as str)->parse_i64() + if a >= 0 && a <= 255 && b >= 0 && b <= 255 && c >= 0 && c <= 255 && d >= 0 && d <= 255 + parts->free_with_items() + return net.pack_addr(a, b, c, d), true + parts->free_with_items() + + query := net.build_dns_query(domain, DNS_TYPE_A) + + // TODO: this probably shouldnt be hardcoded + ~s, ok := net.create_udp_client("1.1.1.1", 53) + if !ok + query->free() + return -1, false + + s->send_to(s->addr, query->data, query->size) + query->free() + pkt := s->receive(1024) + s->close_and_free() + + // TODO: do actual parsing + + pos := 12 // skip header (12 bytes) + + while pkt->data[pos] != 0 + pos += pkt->data[pos] + 1 // skip question + + pos += 5 // skip null byte, type(2), class(2) + + pos += 12 // skip name(2), type(2), class(2), ttl(4), rdlength(2) + + 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) + pkt->free() + return out, true func net.encode_dns_name[domain: str] : Blob domain_len := domain->len() @@ -168,33 +234,3 @@ func net.build_dns_query[domain_name: str, record_type: i64] : Blob name->free() return out - -// TODO: dont resolve if its already an IP -func net.resolve[domain: str] : i64, bool - query := net.build_dns_query(domain, DNS_TYPE_A) - - // TODO: this probably shouldnt be hardcoded - ~s, ok := net.create_udp_client(net.pack_addr(1, 1, 1, 1), 53) - if !ok - query->free() - return -1, false - - s->send_to(s->addr, query->data, query->size) - query->free() - pkt := s->receive(1024) - s->close_and_free() - - // TODO: do actual parsing - - pos := 12 // skip header (12 bytes) - - while pkt->data[pos] != 0 - pos += pkt->data[pos] + 1 // skip question - - pos += 5 // skip null byte, type(2), class(2) - - pos += 12 // skip name(2), type(2), class(2), ttl(4), rdlength(2) - - 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) - pkt->free() - return out, true diff --git a/src/std/std.zr b/src/std/std.zr index d082317..4073f71 100644 --- a/src/std/std.zr +++ b/src/std/std.zr @@ -76,6 +76,9 @@ func mem.alloc[size: i64] : ptr return blk as ptr + MEM_BLOCK_SIZE +func mem.free[x: any] : void + ptr.free(x as ptr) + func ptr.free[x: ptr] : void if x == 0 return 0 @@ -372,7 +375,7 @@ func io.write_binary_file[path: str, content: ptr, size: i64] : bool return true func str.free[s: str] : void - (s as ptr)->free() + mem.free(s) func str.len[s: str] : i64 i := 0 @@ -572,7 +575,7 @@ func str.parse_i64[s: str] : i64 num := 0 while i < len d := s[i] - if d < '0' || d > '9' + if !d->is_digit() break num = num * 10 + (d - '0') i += 1 @@ -591,7 +594,7 @@ func str.hex_encode[s: str, s_len: i64] : str return out func str._hex_digit_to_int[d: u8] : u8 - if d >= '0' && d <= '9' + if d->is_digit() return d - '0' lower : u8 = d | 32 if lower >= 'a' && lower <= 'f' @@ -831,7 +834,7 @@ func Blob.alloc[size: i64] : Blob func Blob.free[buf: Blob] : void buf->data->free() - (buf as ptr)->free() + mem.free(buf) struct Array data: ptr @@ -871,14 +874,14 @@ func Array.push[xs: Array, x: any] : void func Array.free[xs: Array] : void if xs->data != 0 xs->data->free() - (xs as ptr)->free() + mem.free(xs) func Array.free_with_items[xs: Array] : void if xs->data != 0 for i in 0..xs->size - (xs->nth(i) as ptr)->free() + mem.free(xs->nth(i)) xs->data->free() - (xs as ptr)->free() + mem.free(xs) func Array.pop[xs: Array] : any if xs->size == 0 @@ -1004,7 +1007,7 @@ func HashMap.delete[map: HashMap, key: str] : void map->table->set(index, current->next) current->key->free() - (current as ptr)->free() + mem.free(current) return 0 prev = current @@ -1024,10 +1027,10 @@ func HashMap.free[map: HashMap] : void tmp := current current = current->next tmp->key->free() - (tmp as ptr)->free() + mem.free(tmp) map->table->free() - (map as ptr)->free() + mem.free(map) func os.exit[code: i64] : void _builtin_syscall(SYS_exit, code)