support up to 6 args, euler
This commit is contained in:
12
examples/euler1.zr
Normal file
12
examples/euler1.zr
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
func print_i64[x : I64] : I64
|
||||||
|
printf("%ld\n", x)
|
||||||
|
|
||||||
|
func main[] : I64
|
||||||
|
let sum: I64 = 0
|
||||||
|
|
||||||
|
let i: I64 = 0
|
||||||
|
while i < 1000
|
||||||
|
if i % 5 == 0 || i % 3 == 0
|
||||||
|
sum = sum + i
|
||||||
|
i = i + 1
|
||||||
|
print_i64(sum)
|
||||||
27
examples/euler10.zr
Normal file
27
examples/euler10.zr
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
func print_i64[x : I64] : I64
|
||||||
|
printf("%ld\n", x)
|
||||||
|
|
||||||
|
func is_prime[n: I64]: I64
|
||||||
|
if n <= 1
|
||||||
|
return 0
|
||||||
|
if n == 2 || n == 3
|
||||||
|
return 1
|
||||||
|
if n % 2 == 0 || n % 3 == 0
|
||||||
|
return 0
|
||||||
|
|
||||||
|
let i: I64 = 5
|
||||||
|
while i * i <= n
|
||||||
|
if n % i == 0 || n % (i + 2) == 0
|
||||||
|
return 0
|
||||||
|
i = i + 6
|
||||||
|
return 1
|
||||||
|
|
||||||
|
func main[] : I64
|
||||||
|
let sum: I64 = 0
|
||||||
|
|
||||||
|
let i: I64 = 0
|
||||||
|
while i < 2000000
|
||||||
|
if is_prime(i)
|
||||||
|
sum = sum + i
|
||||||
|
i = i + 1
|
||||||
|
print_i64(sum)
|
||||||
27
examples/euler14.zr
Normal file
27
examples/euler14.zr
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
func print_i64[x : I64] : I64
|
||||||
|
printf("%ld\n", x)
|
||||||
|
|
||||||
|
func collatz_num[n: I64] : I64
|
||||||
|
if n % 2 == 0
|
||||||
|
return n / 2
|
||||||
|
return n * 3 + 1
|
||||||
|
|
||||||
|
func collatz_seq[n: I64]: I64
|
||||||
|
let i: I64 = 1
|
||||||
|
while n != 1
|
||||||
|
n = collatz_num(n)
|
||||||
|
i = i + 1
|
||||||
|
return i
|
||||||
|
|
||||||
|
func main[] : I64
|
||||||
|
let max: I64 = 0
|
||||||
|
let max_index: I64 = 0
|
||||||
|
|
||||||
|
let i: I64 = 1
|
||||||
|
while i < 1000000
|
||||||
|
let seq: I64 = collatz_seq(i)
|
||||||
|
if seq > max
|
||||||
|
max = seq
|
||||||
|
max_index = i
|
||||||
|
i = i + 1
|
||||||
|
print_i64(max_index)
|
||||||
16
examples/euler2.zr
Normal file
16
examples/euler2.zr
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
func print_i64[x : I64] : I64
|
||||||
|
printf("%ld\n", x)
|
||||||
|
|
||||||
|
func main[] : I64
|
||||||
|
let sum: I64 = 0
|
||||||
|
let a: I64 = 0
|
||||||
|
let b: I64 = 1
|
||||||
|
|
||||||
|
while a < 4000000
|
||||||
|
if a % 2 == 0
|
||||||
|
sum = sum + a
|
||||||
|
let temp: I64 = b
|
||||||
|
b = a + b
|
||||||
|
a = temp
|
||||||
|
|
||||||
|
print_i64(sum)
|
||||||
14
examples/euler3.zr
Normal file
14
examples/euler3.zr
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
func print_i64[x : I64] : I64
|
||||||
|
printf("%ld\n", x)
|
||||||
|
|
||||||
|
func main[] : I64
|
||||||
|
let n: I64 = 600851475143
|
||||||
|
let f: I64 = 2
|
||||||
|
|
||||||
|
while f * f <= n
|
||||||
|
if n % f == 0
|
||||||
|
n = n / f
|
||||||
|
else
|
||||||
|
f = f + 1
|
||||||
|
|
||||||
|
print_i64(n)
|
||||||
21
examples/euler5.zr
Normal file
21
examples/euler5.zr
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
func print_i64[x : I64] : I64
|
||||||
|
printf("%ld\n", x)
|
||||||
|
|
||||||
|
func gcd[a: I64, b: I64] : I64
|
||||||
|
while b != 0
|
||||||
|
let tmp: I64 = b
|
||||||
|
b = a % b
|
||||||
|
a = tmp
|
||||||
|
return a
|
||||||
|
|
||||||
|
func lcm[a: I64, b: I64] : I64
|
||||||
|
return (a * b) / gcd(a, b)
|
||||||
|
|
||||||
|
func main[] : I64
|
||||||
|
let out: I64 = 1
|
||||||
|
|
||||||
|
let i: I64 = 1
|
||||||
|
while i < 21
|
||||||
|
out = lcm(out, i)
|
||||||
|
i = i + 1
|
||||||
|
print_i64(out)
|
||||||
18
examples/euler6.zr
Normal file
18
examples/euler6.zr
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
func print_i64[x : I64] : I64
|
||||||
|
printf("%ld\n", x)
|
||||||
|
|
||||||
|
func main[] : I64
|
||||||
|
let sum_of_squares: I64 = 0
|
||||||
|
let i: I64 = 1
|
||||||
|
while i < 101
|
||||||
|
sum_of_squares = sum_of_squares + i * i
|
||||||
|
i = i + 1
|
||||||
|
|
||||||
|
let square_of_sum: I64 = 0
|
||||||
|
i = 1
|
||||||
|
while i < 101
|
||||||
|
square_of_sum = square_of_sum + i
|
||||||
|
i = i + 1
|
||||||
|
square_of_sum = square_of_sum * square_of_sum
|
||||||
|
|
||||||
|
print_i64(square_of_sum - sum_of_squares)
|
||||||
29
examples/euler7.zr
Normal file
29
examples/euler7.zr
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
func print_i64[x : I64] : I64
|
||||||
|
printf("%ld\n", x)
|
||||||
|
|
||||||
|
func is_prime[n: I64]: I64
|
||||||
|
if n <= 1
|
||||||
|
return 0
|
||||||
|
if n == 2 || n == 3
|
||||||
|
return 1
|
||||||
|
if n % 2 == 0 || n % 3 == 0
|
||||||
|
return 0
|
||||||
|
|
||||||
|
let i: I64 = 5
|
||||||
|
while i * i <= n
|
||||||
|
if n % i == 0 || n % (i + 2) == 0
|
||||||
|
return 0
|
||||||
|
i = i + 6
|
||||||
|
return 1
|
||||||
|
|
||||||
|
func main[] : I64
|
||||||
|
let found: I64 = 0
|
||||||
|
|
||||||
|
let i: I64 = 1
|
||||||
|
while 1
|
||||||
|
if is_prime(i)
|
||||||
|
found = found + 1
|
||||||
|
if found == 10001
|
||||||
|
print_i64(i)
|
||||||
|
return 0
|
||||||
|
i = i + 1
|
||||||
14
examples/euler9.zr
Normal file
14
examples/euler9.zr
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
func print_i64[x : I64] : I64
|
||||||
|
printf("%ld\n", x)
|
||||||
|
|
||||||
|
func main[] : I64
|
||||||
|
let a: I64 = 1
|
||||||
|
while a < 1000
|
||||||
|
let b: I64 = 1
|
||||||
|
while b < 1000
|
||||||
|
let c: I64 = 1000 - b - a
|
||||||
|
if a * a + b * b == c * c
|
||||||
|
print_i64(a * b * c)
|
||||||
|
return 0
|
||||||
|
b = b + 1
|
||||||
|
a = a + 1
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
func print_i64[x : I64] : I64
|
func print_i64[x : I64] : I64
|
||||||
printf("%d\n", x)
|
printf("%ld\n", x)
|
||||||
|
|
||||||
func main[] : I64
|
func main[] : I64
|
||||||
let a: I64 = 0
|
let a: I64 = 0
|
||||||
|
|||||||
@@ -68,6 +68,18 @@ 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 {
|
fn label(&mut self) -> String {
|
||||||
self.label_counter += 1;
|
self.label_counter += 1;
|
||||||
format!(".L{}", self.label_counter)
|
format!(".L{}", self.label_counter)
|
||||||
@@ -158,8 +170,7 @@ print equ puts
|
|||||||
return_type,
|
return_type,
|
||||||
body,
|
body,
|
||||||
} => {
|
} => {
|
||||||
assert!(params.len() <= 1); // TODO
|
assert!(return_type.lexeme == "I64"); // TODO
|
||||||
assert!(return_type.lexeme == "I64");
|
|
||||||
|
|
||||||
writeln!(&mut self.output, "global {}", name.lexeme)?;
|
writeln!(&mut self.output, "global {}", name.lexeme)?;
|
||||||
writeln!(&mut self.output, "{}:", name.lexeme)?;
|
writeln!(&mut self.output, "{}:", name.lexeme)?;
|
||||||
@@ -167,17 +178,20 @@ print equ puts
|
|||||||
writeln!(&mut self.output, " mov rbp, rsp")?;
|
writeln!(&mut self.output, " mov rbp, rsp")?;
|
||||||
writeln!(&mut self.output, " sub rsp, 256")?; // TODO
|
writeln!(&mut self.output, " sub rsp, 256")?; // TODO
|
||||||
|
|
||||||
if params.len() == 1 {
|
for (i, param) in params.iter().enumerate() {
|
||||||
let offset = env.define_var(
|
let offset = env
|
||||||
params.first().unwrap().var_name.lexeme.clone(),
|
.define_var(param.var_name.lexeme.clone(), param.var_type.lexeme.clone());
|
||||||
params.first().unwrap().var_type.lexeme.clone(),
|
writeln!(
|
||||||
);
|
&mut self.output,
|
||||||
writeln!(&mut self.output, " mov QWORD [rbp-{}], rdi", offset)?;
|
" mov QWORD [rbp-{}], {}",
|
||||||
|
offset,
|
||||||
|
CodegenX86_64::nth_register(i)
|
||||||
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.compile_stmt(env, *body)?;
|
self.compile_stmt(env, *body)?;
|
||||||
|
|
||||||
writeln!(&mut self.output, " mov rax, 0")?;
|
writeln!(&mut self.output, " mov rax, 0")?; // TODO: remove default return value
|
||||||
writeln!(&mut self.output, " mov rsp, rbp")?;
|
writeln!(&mut self.output, " mov rsp, rbp")?;
|
||||||
writeln!(&mut self.output, " pop rbp")?;
|
writeln!(&mut self.output, " pop rbp")?;
|
||||||
writeln!(&mut self.output, " ret")?;
|
writeln!(&mut self.output, " ret")?;
|
||||||
@@ -215,8 +229,8 @@ print equ puts
|
|||||||
writeln!(&mut self.output, " mov rax, rdx")?;
|
writeln!(&mut self.output, " mov rax, rdx")?;
|
||||||
}
|
}
|
||||||
TokenType::Xor => writeln!(&mut self.output, " xor rax, rbx")?,
|
TokenType::Xor => writeln!(&mut self.output, " xor rax, rbx")?,
|
||||||
TokenType::And => todo!(),
|
TokenType::And => writeln!(&mut self.output, " and rax, rbx")?,
|
||||||
TokenType::Or => todo!(),
|
TokenType::Or => writeln!(&mut self.output, " or rax, rbx")?,
|
||||||
TokenType::DoubleEqual => {
|
TokenType::DoubleEqual => {
|
||||||
writeln!(&mut self.output, " cmp rax, rbx")?;
|
writeln!(&mut self.output, " cmp rax, rbx")?;
|
||||||
writeln!(&mut self.output, " sete al")?;
|
writeln!(&mut self.output, " sete al")?;
|
||||||
@@ -254,6 +268,7 @@ print equ puts
|
|||||||
Expr::Literal(token) => match token.token_type {
|
Expr::Literal(token) => match token.token_type {
|
||||||
TokenType::Number => writeln!(&mut self.output, " mov rax, {}", token.lexeme)?,
|
TokenType::Number => writeln!(&mut self.output, " mov rax, {}", token.lexeme)?,
|
||||||
TokenType::String => {
|
TokenType::String => {
|
||||||
|
// TODO: actual string parsing in the tokenizer
|
||||||
let value = &token.lexeme[1..token.lexeme.len() - 1].replace("\\n", "\n");
|
let value = &token.lexeme[1..token.lexeme.len() - 1].replace("\\n", "\n");
|
||||||
let charcodes = value
|
let charcodes = value
|
||||||
.chars()
|
.chars()
|
||||||
@@ -320,16 +335,13 @@ print equ puts
|
|||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO
|
for (i, arg) in args.iter().enumerate() {
|
||||||
assert!(args.len() <= 2);
|
self.compile_expr(env, arg.clone())?;
|
||||||
if args.len() == 1 {
|
writeln!(
|
||||||
self.compile_expr(env, args.first().unwrap().clone())?;
|
&mut self.output,
|
||||||
writeln!(&mut self.output, " mov rdi, rax")?;
|
" mov {}, rax",
|
||||||
} else if args.len() == 2 {
|
CodegenX86_64::nth_register(i)
|
||||||
self.compile_expr(env, args.first().unwrap().clone())?;
|
)?;
|
||||||
writeln!(&mut self.output, " mov rdi, rax")?;
|
|
||||||
self.compile_expr(env, args.get(1).unwrap().clone())?;
|
|
||||||
writeln!(&mut self.output, " mov rsi, rax")?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
writeln!(&mut self.output, " call {}", callee)?;
|
writeln!(&mut self.output, " call {}", callee)?;
|
||||||
|
|||||||
@@ -22,11 +22,10 @@ fn compile_file(path: String) -> Result<(), Box<dyn Error>> {
|
|||||||
let statements = parser.parse()?;
|
let statements = parser.parse()?;
|
||||||
|
|
||||||
let mut codegen = codegen_x86_64::CodegenX86_64::new();
|
let mut codegen = codegen_x86_64::CodegenX86_64::new();
|
||||||
let mut env = codegen_x86_64::Env::new();
|
|
||||||
|
|
||||||
codegen.emit_prologue()?;
|
codegen.emit_prologue()?;
|
||||||
for stmt in statements {
|
for stmt in statements {
|
||||||
codegen.compile_stmt(&mut env, stmt)?;
|
codegen.compile_stmt(&mut codegen_x86_64::Env::new(), stmt)?;
|
||||||
}
|
}
|
||||||
codegen.emit_epilogue()?;
|
codegen.emit_epilogue()?;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user