From 781280060c714f1b3c85207a7a71b7bd99b9df92 Mon Sep 17 00:00:00 2001 From: Toni Date: Sun, 1 Jun 2025 17:30:26 +0200 Subject: [PATCH] string example --- examples/euler1.zr | 2 +- examples/euler10.zr | 2 +- examples/euler14.zr | 2 +- examples/euler2.zr | 2 +- examples/euler3.zr | 2 +- examples/euler5.zr | 2 +- examples/euler6.zr | 2 +- examples/euler7.zr | 2 +- examples/euler9.zr | 2 +- examples/fib.zr | 2 +- examples/strings.zr | 12 ++++++++++ src/codegen_x86_64.rs | 53 ++++++++++++++++++++----------------------- 12 files changed, 47 insertions(+), 38 deletions(-) create mode 100644 examples/strings.zr diff --git a/examples/euler1.zr b/examples/euler1.zr index 5b22afe..5e55a6d 100644 --- a/examples/euler1.zr +++ b/examples/euler1.zr @@ -1,4 +1,4 @@ -func print_i64[x : I64] : I64 +func print_i64[x: I64] : I64 printf("%ld\n", x) func main[] : I64 diff --git a/examples/euler10.zr b/examples/euler10.zr index bed9455..57b3e80 100644 --- a/examples/euler10.zr +++ b/examples/euler10.zr @@ -1,4 +1,4 @@ -func print_i64[x : I64] : I64 +func print_i64[x: I64] : I64 printf("%ld\n", x) func is_prime[n: I64]: I64 diff --git a/examples/euler14.zr b/examples/euler14.zr index ebdab67..10fba0e 100644 --- a/examples/euler14.zr +++ b/examples/euler14.zr @@ -1,4 +1,4 @@ -func print_i64[x : I64] : I64 +func print_i64[x: I64] : I64 printf("%ld\n", x) func collatz_num[n: I64] : I64 diff --git a/examples/euler2.zr b/examples/euler2.zr index 42d0055..64c4117 100644 --- a/examples/euler2.zr +++ b/examples/euler2.zr @@ -1,4 +1,4 @@ -func print_i64[x : I64] : I64 +func print_i64[x: I64] : I64 printf("%ld\n", x) func main[] : I64 diff --git a/examples/euler3.zr b/examples/euler3.zr index ebc099b..9041a03 100644 --- a/examples/euler3.zr +++ b/examples/euler3.zr @@ -1,4 +1,4 @@ -func print_i64[x : I64] : I64 +func print_i64[x: I64] : I64 printf("%ld\n", x) func main[] : I64 diff --git a/examples/euler5.zr b/examples/euler5.zr index 3fd113b..d259053 100644 --- a/examples/euler5.zr +++ b/examples/euler5.zr @@ -1,4 +1,4 @@ -func print_i64[x : I64] : I64 +func print_i64[x: I64] : I64 printf("%ld\n", x) func gcd[a: I64, b: I64] : I64 diff --git a/examples/euler6.zr b/examples/euler6.zr index 1d5d384..ace9130 100644 --- a/examples/euler6.zr +++ b/examples/euler6.zr @@ -1,4 +1,4 @@ -func print_i64[x : I64] : I64 +func print_i64[x: I64] : I64 printf("%ld\n", x) func main[] : I64 diff --git a/examples/euler7.zr b/examples/euler7.zr index 59d33be..9b4c0a8 100644 --- a/examples/euler7.zr +++ b/examples/euler7.zr @@ -1,4 +1,4 @@ -func print_i64[x : I64] : I64 +func print_i64[x: I64] : I64 printf("%ld\n", x) func is_prime[n: I64]: I64 diff --git a/examples/euler9.zr b/examples/euler9.zr index 2588481..02a460b 100644 --- a/examples/euler9.zr +++ b/examples/euler9.zr @@ -1,4 +1,4 @@ -func print_i64[x : I64] : I64 +func print_i64[x: I64] : I64 printf("%ld\n", x) func main[] : I64 diff --git a/examples/fib.zr b/examples/fib.zr index 527fbae..9d25f36 100644 --- a/examples/fib.zr +++ b/examples/fib.zr @@ -1,4 +1,4 @@ -func print_i64[x : I64] : I64 +func print_i64[x: I64] : I64 printf("%ld\n", x) func main[] : I64 diff --git a/examples/strings.zr b/examples/strings.zr new file mode 100644 index 0000000..5b0318b --- /dev/null +++ b/examples/strings.zr @@ -0,0 +1,12 @@ +func print_i64[x: I64] : I64 + printf("%ld\n", x) + +func i64_to_string[n: I64] : String + let x: I64 = malloc(21) + sprintf(x, "%d", n) + return x + +func main[] : I64 + let s: String = i64_to_string(58394) + print_i64(strlen(s)) + free(s) \ No newline at end of file diff --git a/src/codegen_x86_64.rs b/src/codegen_x86_64.rs index 2d6b3d6..a7e50fe 100644 --- a/src/codegen_x86_64.rs +++ b/src/codegen_x86_64.rs @@ -57,6 +57,9 @@ macro_rules! emit { }; } +static REGISTERS: [&str; 6] = ["rdi", "rsi", "rdx", "rcx", "r8", "r9"]; +static TYPES: [&str; 2] = ["I64", "String"]; + pub struct CodegenX86_64 { output: String, data_section: String, @@ -74,18 +77,6 @@ impl CodegenX86_64 { } } - fn nth_register(n: usize) -> &'static str { - match n { - 0 => "rdi", - 1 => "rsi", - 2 => "rdx", - 3 => "rcx", - 4 => "r8", - 5 => "r9", - _ => todo!("only up to 6 arguments supported"), - } - } - fn label(&mut self) -> String { self.label_counter += 1; format!(".L{}", self.label_counter) @@ -94,8 +85,7 @@ impl CodegenX86_64 { pub fn get_output(&self) -> String { format!( "section .data -{} -{}", +{}{}", self.data_section, self.output ) } @@ -105,7 +95,11 @@ impl CodegenX86_64 { &mut self.output, " section .text +extern malloc +extern free extern printf +extern sprintf +extern strlen extern puts print equ puts ", @@ -128,7 +122,9 @@ print equ puts initializer, } => { // TODO: types - assert!(var_type.lexeme == "I64"); + if !TYPES.contains(&var_type.lexeme.as_str()) { + return error!(&name.loc, format!("unknown type: {}", var_type.lexeme)); + } self.compile_expr(env, initializer)?; let offset = env.define_var(name.lexeme.clone(), var_type.lexeme); @@ -176,7 +172,9 @@ print equ puts return_type, body, } => { - assert!(return_type.lexeme == "I64"); // TODO + if !TYPES.contains(&return_type.lexeme.as_str()) { + return error!(&name.loc, format!("unknown type: {}", return_type.lexeme)); + } emit!(&mut self.output, "global {}", name.lexeme); emit!(&mut self.output, "{}:", name.lexeme); @@ -187,12 +185,11 @@ print equ puts for (i, param) in params.iter().enumerate() { let offset = env .define_var(param.var_name.lexeme.clone(), param.var_type.lexeme.clone()); - emit!( - &mut self.output, - " mov QWORD [rbp-{}], {}", - offset, - CodegenX86_64::nth_register(i), - ); + let reg = match REGISTERS.get(i) { + Some(x) => x, + None => return error!(&name.loc, "only up to 6 params allowed"), + }; + emit!(&mut self.output, " mov QWORD [rbp-{}], {}", offset, reg,); } self.compile_stmt(env, *body)?; @@ -350,7 +347,7 @@ print equ puts } Expr::Call { callee, - paren: _, + paren, args, } => { let callee = match *callee { @@ -360,11 +357,11 @@ print equ puts for (i, arg) in args.iter().enumerate() { self.compile_expr(env, arg.clone())?; - emit!( - &mut self.output, - " mov {}, rax", - CodegenX86_64::nth_register(i), - ); + let reg = match REGISTERS.get(i) { + Some(x) => x, + None => return error!(&paren.loc, "only up to 6 args allowed"), + }; + emit!(&mut self.output, " mov {}, rax", reg,); } emit!(&mut self.output, " call {}", callee);