From e84419f0cfb3d7d08bccff2626bd21823c4b275c Mon Sep 17 00:00:00 2001 From: Toni Date: Sun, 1 Jun 2025 19:02:25 +0200 Subject: [PATCH] euler8, euler12 --- examples/euler12.zr | 26 ++++++++++++++++++++++++++ examples/euler8.zr | 22 ++++++++++++++++++++++ src/codegen_x86_64.rs | 38 +++++++++++++++++++++++++++++++++++++- src/main.rs | 23 ++++++++++++++++------- 4 files changed, 101 insertions(+), 8 deletions(-) create mode 100644 examples/euler12.zr create mode 100644 examples/euler8.zr diff --git a/examples/euler12.zr b/examples/euler12.zr new file mode 100644 index 0000000..c358b2e --- /dev/null +++ b/examples/euler12.zr @@ -0,0 +1,26 @@ +func print_i64[x: I64] : I64 + printf("%ld\n", x) + +func num_divisors[n: I64] : I64 + let end: I64 = isqrt(n) + + let result: I64 = 0 + let i: I64 = 1 + while i < end + 1 + if n % i == 0 + result = result + 2 + i = i + 1 + + if end * end == n + result = result - 1 + return result + +func main[] : I64 + let n: I64 = 0 + let i: I64 = 1 + while 1 + n = n + i + if num_divisors(n) > 500 + print_i64(n) + return 0 + i = i + 1 \ No newline at end of file diff --git a/examples/euler8.zr b/examples/euler8.zr new file mode 100644 index 0000000..df3a131 --- /dev/null +++ b/examples/euler8.zr @@ -0,0 +1,22 @@ +func print_i64[x: I64] : I64 + printf("%ld\n", x) + +func char_to_i64[c: I64]: I64 + return c - 48 + +func main[] : I64 + let n: String = "7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450" + + let out: I64 = 0 + let i: I64 = 0 + let max: I64 = strlen(n) - 13 + while i < max + let s: I64 = 1 + let j: I64 = 0 + while j < 13 + s = s * char_to_i64(nth(n, i + j)) + j = j + 1 + if s > out + out = s + i = i + 1 + print_i64(out) \ No newline at end of file diff --git a/src/codegen_x86_64.rs b/src/codegen_x86_64.rs index e1e4a70..f7c55a2 100644 --- a/src/codegen_x86_64.rs +++ b/src/codegen_x86_64.rs @@ -102,6 +102,7 @@ extern sprintf extern strlen extern strcmp extern puts +extern system print equ puts ; generated with clang @@ -131,6 +132,41 @@ strrev: pop rbx pop r14 ret + +isqrt: + xor rax, rax + mov rcx, 1 + mov rbx, rdi + shl rcx, 62 +.LBB0_3: + cmp rcx, 0 + je .LBB0_5 + cmp rcx, rbx + jbe .LBB0_4 + shr rcx, 2 + jmp .LBB0_3 +.LBB0_4: + cmp rcx, 0 + je .LBB0_5 + mov rdx, rax + add rdx, rcx + cmp rbx, rdx + jb .LBB0_7 + sub rbx, rdx + shr rax, 1 + add rax, rcx + jmp .LBB0_6 +.LBB0_7: + shr rax, 1 +.LBB0_6: + shr rcx, 2 + jmp .LBB0_4 +.LBB0_5: + ret + +nth: + movzx rax, byte [rdi + rsi] + ret ", ); Ok(()) @@ -381,7 +417,7 @@ strrev: } => { let callee = match *callee { Expr::Variable(name) => name.lexeme, - _ => todo!(), + _ => return error!(&paren.loc, "tried to call a non-constant expression"), }; for (i, arg) in args.iter().enumerate() { diff --git a/src/main.rs b/src/main.rs index ee0f5c0..e6f2d18 100644 --- a/src/main.rs +++ b/src/main.rs @@ -35,20 +35,29 @@ fn compile_file(path: String) -> Result<(), ZernError> { } codegen.emit_epilogue()?; - // TODO: handle error - fs::write("out.s", codegen.get_output()).unwrap(); + if fs::write("out.s", codegen.get_output()).is_err() { + eprintln!("\x1b[91mERROR\x1b[0m: failed to write to out.s"); + process::exit(1); + } - // TODO: stop on nasm/gcc error - Command::new("nasm") + if !Command::new("nasm") .args(["-f", "elf64", "-o", "out.o", "out.s"]) .status() - .unwrap(); + .unwrap() + .success() + { + process::exit(1); + } // TODO: drop libc entirely - Command::new("./musl-1.2.4/root/bin/musl-gcc") + if !Command::new("./musl-1.2.4/root/bin/musl-gcc") .args(["-static", "-o", "out", "out.o"]) .status() - .unwrap(); + .unwrap() + .success() + { + process::exit(1); + } Ok(()) }