diff --git a/examples/arrays.zr b/examples/arrays.zr new file mode 100644 index 0000000..3af352d --- /dev/null +++ b/examples/arrays.zr @@ -0,0 +1,10 @@ +func main[] : I64 + let xs: Array = Array.new() + Array.push(xs, 5242) + Array.push(xs, 6533) + Array.push(xs, 4574) + + for i in 0:Array.size(xs) + xs + |> Array.nth(i) + |> print_i64() \ No newline at end of file diff --git a/examples/euler12.zr b/examples/euler12.zr index 988c239..2afa3d2 100644 --- a/examples/euler12.zr +++ b/examples/euler12.zr @@ -1,5 +1,5 @@ func num_divisors[n: I64] : I64 - let end: I64 = isqrt(n) + let end: I64 = Math.isqrt(n) let result: I64 = 0 for i in 1:end+1 @@ -13,7 +13,7 @@ func num_divisors[n: I64] : I64 func main[] : I64 let n: I64 = 0 let i: I64 = 1 - while 1 + while true n = n + i if num_divisors(n) > 500 print_i64(n) diff --git a/examples/euler7.zr b/examples/euler7.zr index 821b0fd..ec9e5ec 100644 --- a/examples/euler7.zr +++ b/examples/euler7.zr @@ -2,7 +2,7 @@ func main[] : I64 let found: I64 = 0 let i: I64 = 1 - while 1 + while true if Math.is_prime(i) found = found + 1 if found == 10001 diff --git a/examples/euler8.zr b/examples/euler8.zr index bf0f024..6a58314 100644 --- a/examples/euler8.zr +++ b/examples/euler8.zr @@ -7,7 +7,7 @@ func main[] : I64 let s: I64 = 1 let j: I64 = 0 while j < 13 - s = s * Char.to_i64(nth(n, i + j)) + s = s * Char.to_i64(String.nth(n, i + j)) j = j + 1 if s > out out = s diff --git a/src/codegen_x86_64.rs b/src/codegen_x86_64.rs index effbc66..2867a7a 100644 --- a/src/codegen_x86_64.rs +++ b/src/codegen_x86_64.rs @@ -58,7 +58,7 @@ macro_rules! emit { } static REGISTERS: [&str; 6] = ["rdi", "rsi", "rdx", "rcx", "r8", "r9"]; -static TYPES: [&str; 5] = ["I64", "String", "Bool", "Ptr", "Char"]; +static TYPES: [&str; 6] = ["I64", "String", "Bool", "Ptr", "Char", "Array"]; pub struct CodegenX86_64 { output: String, @@ -97,6 +97,8 @@ impl CodegenX86_64 { " section .text extern malloc +extern calloc +extern realloc extern free extern printf extern sprintf @@ -117,11 +119,11 @@ extern exit extern gettimeofday copystr equ strdup -nth: +String.nth: movzx rax, byte [rdi + rsi] ret -set: +String.set: mov [rdi + rsi], dl ret @@ -142,7 +144,58 @@ time: pop rbx ret -isqrt: +Array.new: + mov rdi, 1 + mov rsi, 24 + jmp calloc + +Array.nth: + mov rax, [rdi] + mov rax, [rax + rsi*8] + ret + +Array.push: + push r14 + push rbx + push rax + mov r14, rsi + mov rbx, rdi + mov rax, [rdi] + mov rcx, [rdi + 16] + cmp rcx, [rdi + 8] + jne .no_realloc + lea rdx, [rcx + rcx] + mov rsi, 4 + test rcx, rcx + cmovnz rsi, rdx + mov [rbx + 8], rsi + shl rsi, 3 + mov rdi, rax + call realloc + mov [rbx], rax + mov rcx, [rbx + 16] +.no_realloc: + mov [rax + rcx*8], r14 + inc qword [rbx + 16] + add rsp, 8 + pop rbx + pop r14 + ret + +Array.size: + mov rax, [rdi + 16] + ret + +Array.free: + push rbx + mov rbx, rdi + mov rdi, [rdi] + call free + mov rdi, rbx + pop rbx + jmp free + +Math.isqrt: xor rax, rax mov rcx, 1 mov rbx, rdi @@ -400,7 +453,12 @@ isqrt: } 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") + .replace("\\r", "\r") + .replace("\\t", "\t") + .replace("\\033", "\x1b") + .replace("\\0", "\0"); if value.is_empty() { emit!(&mut self.data_section, " S{} db 0", self.data_counter); diff --git a/src/std.zr b/src/std.zr index 1c8e8e4..10ee35d 100644 --- a/src/std.zr +++ b/src/std.zr @@ -23,12 +23,10 @@ func strrev[s: String] : String let len: I64 = strlen(s) let out: String = malloc(len + 1) - let i: I64 = 0 - while i < len - let c: Char = nth(s, len - i - 1) - set(out, i, c) - i = i + 1 - set(out, len, 0) + for i in 0:len + let c: Char = String.nth(s, len - i - 1) + String.set(out, i, c) + String.set(out, len, 0) return out func IO.read_file[path: String]: String @@ -43,7 +41,7 @@ func IO.read_file[path: String]: String let buffer: String = malloc(size + 1) let n: I64 = fread(buffer, 1, size, file) - set(buffer, n, 0) + String.set(buffer, n, 0) return buffer func Char.to_i64[c: Char]: I64 @@ -78,10 +76,8 @@ func Math.abs[n: I64] : I64 func Math.pow[b: I64, e: I64] : I64 let out: I64 = 1 - let i: I64 = 0 - while i < e + for i in 0:e out = out * b - i = i + 1 return out func Math.lcm[a: I64, b: I64] : I64 diff --git a/test.zr b/test.zr index d3f446a..c4bc77a 100644 --- a/test.zr +++ b/test.zr @@ -1,5 +1,6 @@ func run_test[x: String] : I64 - printf("Building %s...", x) + // TODO: escape sequences + printf("\033[93mBuilding %s...\033[0m", x) let cmd: String = concat("./target/release/zern examples/", x) let build_start_time: I64 = time() @@ -15,12 +16,12 @@ func run_test[x: String] : I64 exit(1) let run_end_time: I64 = time() - printf("Running %s... %ldms\n", x, run_end_time - run_start_time) + printf("\033[93mRunning %s...\033[0m %ldms\n", x, run_end_time - run_start_time) func main[] : I64 system("cargo build --release") - // TODO + // TODO: listdir run_test("euler1.zr") run_test("euler2.zr") run_test("euler3.zr")