diff --git a/examples/chip8.zr b/examples/chip8.zr index 747bce7..fba8a54 100644 --- a/examples/chip8.zr +++ b/examples/chip8.zr @@ -47,9 +47,7 @@ func chip8_create[] : CHIP8 func chip8_disassemble[c: CHIP8, ins_count: i64] : void for i in 0..ins_count - io.print("0x") - io.print_i64_hex(c->pc) - io.print(": ") + io.printf("0x%x: ", c->pc) let high: i64 = c->memory[c->pc] let low: i64 = c->memory[c->pc + 1] @@ -69,179 +67,82 @@ func chip8_disassemble[c: CHIP8, ins_count: i64] : void else if nnn == 0x0ee io.println("RET") else - io.print("SYS ") - io.println_i64(nnn) + io.printf("SYS %d\n", nnn) else if op == 0x1 - io.print("JP 0x") - io.print_i64_hex(nnn) - io.print("\n") + io.printf("JP 0x%x\n", nnn) else if op == 0x2 - io.print("CALL ") - io.println_i64(nnn) + io.printf("CALL %d\n", nnn) else if op == 0x3 - io.print("SE V") - io.print_i64_hex(x) - io.print(", ") - io.println_i64(kk) + io.printf("SE V%x, %d\n", x, kk) else if op == 0x4 - io.print("SNE V") - io.print_i64_hex(x) - io.print(", ") - io.println_i64(kk) + io.printf("SNE V%x, %d\n", x, kk) else if op == 0x5 - io.print("SE V") - io.print_i64_hex(x) - io.print(", V") - io.print_i64_hex(y) - io.print("\n") + io.printf("SE V%x, V%x\n", x, y) else if op == 0x6 - io.print("LD V") - io.print_i64_hex(x) - io.print(", ") - io.println_i64(kk) + io.printf("LD V%x, %d\n", x, kk) else if op == 0x7 - io.print("ADD V") - io.print_i64_hex(x) - io.print(", ") - io.println_i64(kk) + io.printf("ADD V%x, %d\n", x, kk) else if op == 0x8 if n == 0x0 - io.print("LD V") - io.print_i64_hex(x) - io.print(", V") - io.print_i64_hex(y) - io.print("\n") + io.printf("LD V%x, V%x\n", x, y) else if n == 0x1 - io.print("OR V") - io.print_i64_hex(x) - io.print(", V") - io.print_i64_hex(y) - io.print("\n") + io.printf("OR V%x, V%x\n", x, y) else if n == 0x2 - io.print("AND V") - io.print_i64_hex(x) - io.print(", V") - io.print_i64_hex(y) - io.print("\n") + io.printf("AND V%x, V%x\n", x, y) else if n == 0x3 - io.print("XOR V") - io.print_i64_hex(x) - io.print(", V") - io.print_i64_hex(y) - io.print("\n") + io.printf("XOR V%x, V%x\n", x, y) else if n == 0x4 - io.print("ADD V") - io.print_i64_hex(x) - io.print(", V") - io.print_i64_hex(y) - io.print("\n") + io.printf("ADD V%x, V%x\n", x, y) else if n == 0x5 - io.print("SUB V") - io.print_i64_hex(x) - io.print(", V") - io.print_i64_hex(y) - io.print("\n") + io.printf("SUB V%x, V%x\n", x, y) else if n == 0x6 - io.print("SHR V") - io.print_i64_hex(x) - io.print("\n") + io.printf("SHR V%x\n", x) else if n == 0x7 - io.print("SUBN V") - io.print_i64_hex(x) - io.print(", V") - io.print_i64_hex(y) - io.print("\n") + io.printf("SUBN V%x, V%x\n", x, y) else if n == 0xE - io.print("SHL V") - io.print_i64_hex(x) - io.print("\n") + io.printf("SHL V%x\n", x) else - io.print("??? (") - io.print_i64_hex(ins) - io.println(")") + io.printf("??? (%x)\n", ins) else if op == 0x9 - io.print("SNE V") - io.print_i64_hex(x) - io.print(", V") - io.print_i64_hex(y) - io.print("\n") + io.printf("SNE V%x, V%x\n", x, y) else if op == 0xa - io.print("LD I, 0x") - io.print_i64_hex(nnn) - io.print("\n") + io.printf("LD I, 0x%x\n", nnn) else if op == 0xb - io.print("JP V0, ") - io.println_i64(nnn) + io.printf("JP V0, %d\n", nnn) else if op == 0xc - io.print("RND V") - io.print_i64_hex(x) - io.print(", ") - io.println_i64(kk) + io.printf("RND V%x, %d\n", x, kk) else if op == 0xd - io.print("DRW V") - io.print_i64_hex(x) - io.print(", V") - io.print_i64_hex(y) - io.print(", ") - io.println_i64(n) + io.printf("DRW V%x, V%x, %d\n", x, y, n) else if op == 0xe if kk == 0x9e - io.print("SKP V") - io.print_i64_hex(x) - io.print("\n") + io.printf("SKP V%x\n", x) else if kk == 0xa1 - io.print("SKNP V") - io.print_i64_hex(x) - io.print("\n") + io.printf("SKNP V%x\n", x) else - io.print("??? (") - io.print_i64_hex(ins) - io.println(")") + io.printf("??? (%x)\n", ins) else if op == 0xf if kk == 0x07 - io.print("LD V") - io.print_i64_hex(x) - io.println(", DT") + io.printf("LD V%x, DT\n", x) else if kk == 0x0A - io.print("LD V") - io.print_i64_hex(x) - io.println(", K") + io.printf("LD V%x, K\n", x) else if kk == 0x15 - io.print("LD DT, V") - io.print_i64_hex(x) - io.print("\n") + io.printf("LD DT, V%x\n", x) else if kk == 0x18 - io.print("LD ST, V") - io.print_i64_hex(x) - io.print("\n") + io.printf("LD ST, V%x\n", x) else if kk == 0x1E - io.print("ADD I, V") - io.print_i64_hex(x) - io.print("\n") + io.printf("ADD I, V%x\n", x) else if kk == 0x29 - io.print("LD F, V") - io.print_i64_hex(x) - io.print("\n") + io.printf("LD F, V%x\n", x) else if kk == 0x33 - io.print("LD B, V") - io.print_i64_hex(x) - io.print("\n") + io.printf("LD B, V%x\n", x) else if kk == 0x55 - io.print("LD [I], V") - io.print_i64_hex(x) - io.print("\n") + io.printf("LD [I], V%x\n", x) else if kk == 0x65 - io.print("LD V") - io.print_i64_hex(x) - io.println(", [I]") + io.printf("LD V%x, [I]\n", x) else - io.print("??? (") - io.print_i64_hex(ins) - io.println(")") + io.printf("??? (%x)\n", ins) else - io.print("??? (") - io.print_i64_hex(ins) - io.println(")") + io.printf("??? (%x)\n", ins) func chip8_step[c: CHIP8] : void let high: i64 = c->memory[c->pc] @@ -419,4 +320,4 @@ func main[argc: i64, argv: ptr] : i64 if c->display[x + y * 64] == 1 DrawRectangle(x * 10, y * 10, 10, 10, 0xff000000) - EndDrawing() \ No newline at end of file + EndDrawing() diff --git a/examples/puzzles/euler_01.zr b/examples/puzzles/euler_01.zr index 4d3a314..bf1a808 100644 --- a/examples/puzzles/euler_01.zr +++ b/examples/puzzles/euler_01.zr @@ -4,4 +4,5 @@ func main[] : i64 for i in 0..1000 if i % 5 == 0 || i % 3 == 0 sum = sum + i + io.println_i64(sum) diff --git a/src/analyzer.rs b/src/analyzer.rs index 79591dd..5623270 100644 --- a/src/analyzer.rs +++ b/src/analyzer.rs @@ -165,7 +165,11 @@ impl Analyzer { { // its a function (defined/builtin/extern) if let Some(arity) = self.functions.get(&callee_name.lexeme) { - if *arity >= 0 && *arity != args.len() as i32 { + if *arity >= 0 + && *arity != args.len() as i32 + && callee_name.lexeme != "io.printf" + // TODO: disgusting hack + { return error!( &paren.loc, format!("expected {} arguments, got {}", arity, args.len()) diff --git a/src/codegen_x86_64.rs b/src/codegen_x86_64.rs index fbd2794..0a17f0d 100644 --- a/src/codegen_x86_64.rs +++ b/src/codegen_x86_64.rs @@ -100,7 +100,7 @@ impl<'a> CodegenX86_64<'a> { format!("section .data\n{}{}", self.data_section, self.output) } - pub fn emit_prologue(&mut self, emit_start: bool) -> Result<(), ZernError> { + pub fn emit_prologue(&mut self, use_gcc: bool) -> Result<(), ZernError> { emit!( &mut self.output, "section .note.GNU-stack @@ -145,7 +145,7 @@ _builtin_syscall: " ); - if emit_start { + if !use_gcc { emit!( &mut self.output, " diff --git a/src/main.rs b/src/main.rs index 4bfaef1..b5e4b72 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,6 +13,18 @@ use tokenizer::ZernError; use clap::Parser; +macro_rules! compile_std { + ($codegen:expr, $( $name:literal ),* $(,)? ) => { + $( + compile_file_to( + $codegen, + $name, + include_str!(concat!("std/", $name)).into() + )?; + )* + }; +} + fn compile_file_to( codegen: &mut codegen_x86_64::CodegenX86_64, filename: &str, @@ -63,14 +75,8 @@ fn compile_file(args: Args) -> Result<(), ZernError> { let mut analyzer = analyzer::Analyzer::new(); let mut codegen = codegen_x86_64::CodegenX86_64::new(&mut analyzer); - codegen.emit_prologue(!args.use_gcc)?; - compile_file_to( - &mut codegen, - "syscalls.zr", - include_str!("std/syscalls.zr").into(), - )?; - compile_file_to(&mut codegen, "std.zr", include_str!("std/std.zr").into())?; - compile_file_to(&mut codegen, "net.zr", include_str!("std/net.zr").into())?; + codegen.emit_prologue(args.use_gcc)?; + compile_std!(&mut codegen, "syscalls.zr", "std.zr", "net.zr"); compile_file_to(&mut codegen, filename, source)?; if !args.output_asm { diff --git a/src/std/std.zr b/src/std/std.zr index a4bdcfc..aaac357 100644 --- a/src/std/std.zr +++ b/src/std/std.zr @@ -186,6 +186,36 @@ func mem.write32[x: ptr, d: i64] : void func mem.write64[x: ptr, d: i64] : void _builtin_set64(x, d) +// TODO: we don't have variadics so we manually skip arity checking in the analyzer +func io.printf[s: str, a1: any, a2: any, a3: any, a4: any, a5: any] : void + // TODO: we really shouldn't heap allocate to print something + let args: Array = [a1, a2, a3, a4, a5] + let arg_idx: i64 = 0 + + while s[0] + if s[0] == '%' + s = s + 1 + + if s[0] == 'd' + io.print_i64(array.nth(args, arg_idx)) + arg_idx = arg_idx + 1 + else if s[0] == 'x' + io.print_i64_hex(array.nth(args, arg_idx)) + arg_idx = arg_idx + 1 + else if s[0] == 's' + io.print(array.nth(args, arg_idx)) + arg_idx = arg_idx + 1 + else if (s[0] == 'c') + io.print_char(array.nth(args, arg_idx)) + arg_idx = arg_idx + 1 + else if (s[0] == '%') + io.print_char('%') + else + io.print_char(s[0]) + s = s + 1 + + array.free(args) + func io.print_sized[x: str, size: i64] : void _builtin_syscall(SYS_write, 1, x, size)