Merge remote-tracking branch 'origin/main'
This commit is contained in:
@@ -22,7 +22,7 @@ struct CHIP8
|
|||||||
keyboard_map: Array
|
keyboard_map: Array
|
||||||
|
|
||||||
func chip8_create[] : CHIP8
|
func chip8_create[] : CHIP8
|
||||||
c := new CHIP8
|
c := new* CHIP8
|
||||||
c->memory = mem.alloc(4096)
|
c->memory = mem.alloc(4096)
|
||||||
mem.zero(c->memory, 4096)
|
mem.zero(c->memory, 4096)
|
||||||
c->display = mem.alloc(64*32)
|
c->display = mem.alloc(64*32)
|
||||||
|
|||||||
@@ -2,12 +2,19 @@ func main[] : i64
|
|||||||
s : i64 = must(net.listen?(net.pack_addr(127, 0, 0, 1), 8000))
|
s : i64 = must(net.listen?(net.pack_addr(127, 0, 0, 1), 8000))
|
||||||
|
|
||||||
io.println("Listening on port 8000...")
|
io.println("Listening on port 8000...")
|
||||||
|
|
||||||
resp := mem.alloc(60000)
|
resp := mem.alloc(60000)
|
||||||
|
addr := mem.alloc(16)
|
||||||
while true
|
while true
|
||||||
conn := net.accept(s)
|
conn := net.accept(s, addr)
|
||||||
if conn < 0
|
if conn < 0
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
io.printf("%d.%d.%d.%d:%d\n", addr[4], addr[5], addr[6], addr[7], mem.read16be(addr + 2))
|
||||||
|
|
||||||
|
io.print_sized(resp, n)
|
||||||
|
io.println("")
|
||||||
|
|
||||||
n := net.read(conn, resp, 60000)
|
n := net.read(conn, resp, 60000)
|
||||||
net.send(conn, resp, n)
|
net.send(conn, resp, n)
|
||||||
net.close(conn)
|
net.close(conn)
|
||||||
|
|||||||
@@ -8,5 +8,10 @@ func main[] : i64
|
|||||||
net.UDPPacket.free(pkt)
|
net.UDPPacket.free(pkt)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
io.printf("%d.%d.%d.%d:%d\n", pkt->source_addr[4], pkt->source_addr[5], pkt->source_addr[6], pkt->source_addr[7], mem.read16be(pkt->source_addr + 2))
|
||||||
|
|
||||||
|
io.print_sized(pkt->data, pkt->size)
|
||||||
|
io.println("")
|
||||||
|
|
||||||
net.udp_send_to(s, pkt->source_addr, pkt->data, pkt->size)
|
net.udp_send_to(s, pkt->source_addr, pkt->data, pkt->size)
|
||||||
net.UDPPacket.free(pkt)
|
net.UDPPacket.free(pkt)
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ struct Var {
|
|||||||
pub var_type: String,
|
pub var_type: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const STACK_SIZE: usize = 256; // TODO: eww
|
||||||
|
|
||||||
pub struct Env {
|
pub struct Env {
|
||||||
scopes: Vec<HashMap<String, Var>>,
|
scopes: Vec<HashMap<String, Var>>,
|
||||||
next_offset: usize,
|
next_offset: usize,
|
||||||
@@ -300,7 +302,8 @@ _builtin_environ:
|
|||||||
emit!(&mut self.output, "{}:", name.lexeme);
|
emit!(&mut self.output, "{}:", name.lexeme);
|
||||||
emit!(&mut self.output, " push rbp");
|
emit!(&mut self.output, " push rbp");
|
||||||
emit!(&mut self.output, " mov rbp, rsp");
|
emit!(&mut self.output, " mov rbp, rsp");
|
||||||
emit!(&mut self.output, " sub rsp, 256"); // TODO: eww
|
let stack_size = (STACK_SIZE + 15) & !15;
|
||||||
|
emit!(&mut self.output, " sub rsp, {}", stack_size);
|
||||||
|
|
||||||
match params {
|
match params {
|
||||||
Params::Normal(params) => {
|
Params::Normal(params) => {
|
||||||
@@ -730,16 +733,28 @@ _builtin_environ:
|
|||||||
return error!(&op.loc, "can only take address of variables and functions");
|
return error!(&op.loc, "can only take address of variables and functions");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ExprKind::New(struct_name) => {
|
ExprKind::New {
|
||||||
|
struct_name,
|
||||||
|
use_heap,
|
||||||
|
} => {
|
||||||
let struct_fields = &self.symbol_table.structs[&struct_name.lexeme];
|
let struct_fields = &self.symbol_table.structs[&struct_name.lexeme];
|
||||||
|
|
||||||
let memory_size = struct_fields.len() * 8;
|
let memory_size = struct_fields.len() * 8;
|
||||||
emit!(&mut self.output, " mov rdi, {}", memory_size);
|
|
||||||
emit!(&mut self.output, " call mem.alloc");
|
if *use_heap {
|
||||||
|
emit!(&mut self.output, " mov rdi, {}", memory_size);
|
||||||
|
emit!(&mut self.output, " call mem.alloc");
|
||||||
|
emit!(&mut self.output, " push rax");
|
||||||
|
} else {
|
||||||
|
let aligned_size = (memory_size + 15) & !15;
|
||||||
|
emit!(&mut self.output, " sub rsp, {}", aligned_size);
|
||||||
|
emit!(&mut self.output, " mov rax, rsp");
|
||||||
|
}
|
||||||
emit!(&mut self.output, " push rax");
|
emit!(&mut self.output, " push rax");
|
||||||
|
emit!(&mut self.output, " sub rsp, 8");
|
||||||
emit!(&mut self.output, " mov rdi, rax");
|
emit!(&mut self.output, " mov rdi, rax");
|
||||||
emit!(&mut self.output, " mov rsi, {}", memory_size);
|
emit!(&mut self.output, " mov rsi, {}", memory_size);
|
||||||
emit!(&mut self.output, " call mem.zero");
|
emit!(&mut self.output, " call mem.zero");
|
||||||
|
emit!(&mut self.output, " add rsp, 8");
|
||||||
emit!(&mut self.output, " pop rax");
|
emit!(&mut self.output, " pop rax");
|
||||||
}
|
}
|
||||||
ExprKind::MemberAccess { left, field } => {
|
ExprKind::MemberAccess { left, field } => {
|
||||||
|
|||||||
@@ -121,7 +121,10 @@ pub enum ExprKind {
|
|||||||
op: Token,
|
op: Token,
|
||||||
expr: Box<Expr>,
|
expr: Box<Expr>,
|
||||||
},
|
},
|
||||||
New(Token),
|
New {
|
||||||
|
struct_name: Token,
|
||||||
|
use_heap: bool,
|
||||||
|
},
|
||||||
MemberAccess {
|
MemberAccess {
|
||||||
left: Box<Expr>,
|
left: Box<Expr>,
|
||||||
field: Token,
|
field: Token,
|
||||||
@@ -616,9 +619,13 @@ impl Parser {
|
|||||||
|
|
||||||
Ok(Expr::new(ExprKind::ArrayLiteral(xs)))
|
Ok(Expr::new(ExprKind::ArrayLiteral(xs)))
|
||||||
} else if self.match_token(&[TokenType::KeywordNew]) {
|
} else if self.match_token(&[TokenType::KeywordNew]) {
|
||||||
|
let use_heap = self.match_token(&[TokenType::Star]);
|
||||||
let struct_name =
|
let struct_name =
|
||||||
self.consume(TokenType::Identifier, "expected struct name after 'new'")?;
|
self.consume(TokenType::Identifier, "expected struct name after 'new'")?;
|
||||||
Ok(Expr::new(ExprKind::New(struct_name)))
|
Ok(Expr::new(ExprKind::New {
|
||||||
|
struct_name,
|
||||||
|
use_heap,
|
||||||
|
}))
|
||||||
} else if self.match_token(&[TokenType::Identifier]) {
|
} else if self.match_token(&[TokenType::Identifier]) {
|
||||||
Ok(Expr::new(ExprKind::Variable(self.previous().clone())))
|
Ok(Expr::new(ExprKind::Variable(self.previous().clone())))
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -69,8 +69,9 @@ func net.connect?[packed_host: i64, port: i64] : i64
|
|||||||
mem.free(sa)
|
mem.free(sa)
|
||||||
return s
|
return s
|
||||||
|
|
||||||
func net.accept[s: i64] : i64
|
func net.accept[s: i64, addr: ptr] : i64
|
||||||
return _builtin_syscall(SYS_accept, s, 0, 0)
|
let addrlen = 16
|
||||||
|
return _builtin_syscall(SYS_accept, s, addr, ^addrlen)
|
||||||
|
|
||||||
func net.send[s: i64, data: ptr, size: i64] : void
|
func net.send[s: i64, data: ptr, size: i64] : void
|
||||||
_builtin_syscall(SYS_sendto, s, data, size, 0, 0, 0)
|
_builtin_syscall(SYS_sendto, s, data, size, 0, 0, 0)
|
||||||
@@ -88,14 +89,9 @@ struct net.UDPSocket
|
|||||||
fd: i64
|
fd: i64
|
||||||
addr: ptr
|
addr: ptr
|
||||||
|
|
||||||
struct net.UDPPacket
|
|
||||||
data: ptr
|
|
||||||
source_addr: ptr
|
|
||||||
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()
|
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
|
||||||
@@ -131,8 +127,18 @@ func net.create_udp_server?[packed_host: i64, port: i64] : net.UDPSocket
|
|||||||
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)
|
||||||
|
|
||||||
|
struct net.UDPPacket
|
||||||
|
data: ptr
|
||||||
|
source_addr: ptr
|
||||||
|
size: i64
|
||||||
|
|
||||||
|
func net.UDPPacket.free[pkt: net.UDPPacket] : void
|
||||||
|
mem.free(pkt->data)
|
||||||
|
mem.free(pkt->source_addr)
|
||||||
|
mem.free(pkt)
|
||||||
|
|
||||||
func net.udp_receive[s: net.UDPSocket, size: i64] : net.UDPPacket
|
func net.udp_receive[s: net.UDPSocket, size: i64] : net.UDPPacket
|
||||||
pkt := new net.UDPPacket
|
pkt := new* net.UDPPacket
|
||||||
pkt->data = mem.alloc(size)
|
pkt->data = mem.alloc(size)
|
||||||
pkt->source_addr = mem.alloc(16)
|
pkt->source_addr = mem.alloc(16)
|
||||||
mem.zero(pkt->source_addr, 16)
|
mem.zero(pkt->source_addr, 16)
|
||||||
@@ -146,11 +152,6 @@ func net.UDPSocket.close_and_free[s: net.UDPSocket] : void
|
|||||||
mem.free(s->addr)
|
mem.free(s->addr)
|
||||||
mem.free(s)
|
mem.free(s)
|
||||||
|
|
||||||
func net.UDPPacket.free[pkt: net.UDPPacket] : void
|
|
||||||
mem.free(pkt->data)
|
|
||||||
mem.free(pkt->source_addr)
|
|
||||||
mem.free(pkt)
|
|
||||||
|
|
||||||
const DNS_TYPE_A = 1
|
const DNS_TYPE_A = 1
|
||||||
const DNS_CLASS_IN = 1
|
const DNS_CLASS_IN = 1
|
||||||
const DNS_RECURSION_DESIRED = 256
|
const DNS_RECURSION_DESIRED = 256
|
||||||
@@ -195,7 +196,7 @@ 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
|
||||||
|
|
||||||
// TODO: dont resolve IPs
|
// TODO: dont resolve if its already an IP
|
||||||
func net.resolve?[domain: str] : i64
|
func net.resolve?[domain: str] : i64
|
||||||
err.clear()
|
err.clear()
|
||||||
query := net.build_dns_query(domain, DNS_TYPE_A)
|
query := net.build_dns_query(domain, DNS_TYPE_A)
|
||||||
|
|||||||
@@ -339,7 +339,7 @@ struct io.Buffer
|
|||||||
|
|
||||||
func io.Buffer.alloc?[size: i64] : io.Buffer
|
func io.Buffer.alloc?[size: i64] : io.Buffer
|
||||||
err.clear()
|
err.clear()
|
||||||
buffer := new io.Buffer
|
buffer := new* io.Buffer
|
||||||
buffer->size = size
|
buffer->size = size
|
||||||
buffer->data = mem.alloc?(size)
|
buffer->data = mem.alloc?(size)
|
||||||
if err.check()
|
if err.check()
|
||||||
@@ -403,7 +403,7 @@ func io.read_binary_file?[path: str] : io.Buffer
|
|||||||
err.set(ERR_OPEN_FAILED, "io.read_binary_file?: failed to open file")
|
err.set(ERR_OPEN_FAILED, "io.read_binary_file?: failed to open file")
|
||||||
return 0 as io.Buffer
|
return 0 as io.Buffer
|
||||||
|
|
||||||
buf := new io.Buffer
|
buf := new* io.Buffer
|
||||||
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)
|
||||||
|
|
||||||
@@ -777,10 +777,10 @@ struct Array
|
|||||||
capacity: i64
|
capacity: i64
|
||||||
|
|
||||||
func array.new[] : Array
|
func array.new[] : Array
|
||||||
return new Array
|
return 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 = must(mem.realloc?(xs->data, size * 8)) as ptr
|
||||||
mem.zero(xs->data, size * 8)
|
mem.zero(xs->data, size * 8)
|
||||||
@@ -849,7 +849,7 @@ struct HashMap._Node
|
|||||||
next: HashMap._Node
|
next: HashMap._Node
|
||||||
|
|
||||||
func HashMap.new[] : HashMap
|
func HashMap.new[] : HashMap
|
||||||
map := new HashMap
|
map := new* HashMap
|
||||||
map->table = array.new_preallocated_and_zeroed(HashMap._TABLE_SIZE)
|
map->table = array.new_preallocated_and_zeroed(HashMap._TABLE_SIZE)
|
||||||
return map
|
return map
|
||||||
|
|
||||||
@@ -863,7 +863,7 @@ func HashMap.insert[map: HashMap, key: str, value: any] : void
|
|||||||
return 0
|
return 0
|
||||||
current = current->next
|
current = current->next
|
||||||
|
|
||||||
new_node := new HashMap._Node
|
new_node := new* HashMap._Node
|
||||||
new_node->key = str.make_copy(key)
|
new_node->key = str.make_copy(key)
|
||||||
new_node->value = value
|
new_node->value = value
|
||||||
new_node->next = array.nth(map->table, index)
|
new_node->next = array.nth(map->table, index)
|
||||||
@@ -982,12 +982,10 @@ struct os.Timespec
|
|||||||
func os.sleep[ms: i64] : void
|
func os.sleep[ms: i64] : void
|
||||||
if ms < 0
|
if ms < 0
|
||||||
panic("negative time passed to os.sleep")
|
panic("negative time passed to os.sleep")
|
||||||
// TODO: we really shouldnt need a heap allocation to sleep
|
|
||||||
req := new os.Timespec
|
req := new os.Timespec
|
||||||
req->tv_sec = ms / 1000
|
req->tv_sec = ms / 1000
|
||||||
req->tv_nsec = (ms % 1000) * 1000000
|
req->tv_nsec = (ms % 1000) * 1000000
|
||||||
_builtin_syscall(SYS_nanosleep, req, 0)
|
_builtin_syscall(SYS_nanosleep, req, 0)
|
||||||
mem.free(req)
|
|
||||||
|
|
||||||
func os.urandom?[n: i64]: ptr
|
func os.urandom?[n: i64]: ptr
|
||||||
err.clear()
|
err.clear()
|
||||||
@@ -1022,11 +1020,9 @@ struct os.Timeval
|
|||||||
tv_usec: i64
|
tv_usec: i64
|
||||||
|
|
||||||
func os.time[] : i64
|
func os.time[] : i64
|
||||||
// TODO: we really shouldnt need a heap allocation to check the time
|
|
||||||
tv := new os.Timeval
|
tv := new os.Timeval
|
||||||
_builtin_syscall(SYS_gettimeofday, tv, 0)
|
_builtin_syscall(SYS_gettimeofday, tv, 0)
|
||||||
out := tv->tv_sec * 1000 + tv->tv_usec / 1000
|
out := tv->tv_sec * 1000 + tv->tv_usec / 1000
|
||||||
mem.free(tv)
|
|
||||||
return out
|
return out
|
||||||
|
|
||||||
// voodoo magic
|
// voodoo magic
|
||||||
|
|||||||
@@ -483,7 +483,10 @@ impl<'a> TypeChecker<'a> {
|
|||||||
error!(&op.loc, "can only take address of variables and functions")
|
error!(&op.loc, "can only take address of variables and functions")
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ExprKind::New(struct_name) => {
|
ExprKind::New {
|
||||||
|
struct_name,
|
||||||
|
use_heap: _,
|
||||||
|
} => {
|
||||||
if !self.symbol_table.structs.contains_key(&struct_name.lexeme) {
|
if !self.symbol_table.structs.contains_key(&struct_name.lexeme) {
|
||||||
return error!(
|
return error!(
|
||||||
&struct_name.loc,
|
&struct_name.loc,
|
||||||
|
|||||||
Reference in New Issue
Block a user