From 55a8844699ce31401f4cf8eaefb5d5bc6576af3d Mon Sep 17 00:00:00 2001 From: Toni Date: Sat, 27 Dec 2025 15:38:03 +0100 Subject: [PATCH] fix continue skipping for increment --- examples/raylib.zr | 1 - examples/tokenizer.zr | 15 +++++----- src/codegen_x86_64.rs | 12 ++++++-- test.zr | 70 +++++++++++++++++++++---------------------- 4 files changed, 53 insertions(+), 45 deletions(-) diff --git a/examples/raylib.zr b/examples/raylib.zr index 7b2d984..e56124d 100644 --- a/examples/raylib.zr +++ b/examples/raylib.zr @@ -1,5 +1,4 @@ // needs to be compiled with -m -C="/usr/local/lib/libraylib.a -lm" - extern InitWindow extern SetTargetFPS extern WindowShouldClose diff --git a/examples/tokenizer.zr b/examples/tokenizer.zr index 286eb37..16a0523 100644 --- a/examples/tokenizer.zr +++ b/examples/tokenizer.zr @@ -160,17 +160,20 @@ func scan_token[tokens: array, current: ptr, line: ptr, column: ptr, source: str zern_error(filename, mem.read64(line), mem.read64(column), "expected '.' after '.'") else if c == '/' if match_char('/', current, column, source, source_len) - while !eof(mem.read64(current), source_len) - if peek(mem.read64(current), source, source_len) == 10 // \n - break + while !eof(mem.read64(current), source_len) && peek(mem.read64(current), source, source_len) != 10 advance(current, column, source, source_len) else add_token("Slash", tokens, source, start, mem.read64(current), mem.read64(line), mem.read64(column)) else if c == '&' - add_token("BitAnd", tokens, source, start, mem.read64(current), mem.read64(line), mem.read64(column)) + if match_char('&', current, column, source, source_len) + add_token("LogicalAnd", tokens, source, start, mem.read64(current), mem.read64(line), mem.read64(column)) + else + add_token("BitAnd", tokens, source, start, mem.read64(current), mem.read64(line), mem.read64(column)) else if c == '|' if match_char('>', current, column, source, source_len) add_token("Pipe", tokens, source, start, mem.read64(current), mem.read64(line), mem.read64(column)) + else if match_char('|', current, column, source, source_len) + add_token("LogicalOr", tokens, source, start, mem.read64(current), mem.read64(line), mem.read64(column)) else add_token("BitOr", tokens, source, start, mem.read64(current), mem.read64(line), mem.read64(column)) else if c == '!' @@ -205,9 +208,7 @@ func scan_token[tokens: array, current: ptr, line: ptr, column: ptr, source: str zern_error(filename, mem.read64(line), mem.read64(column), "expected ' after char literal") add_token("Char", tokens, source, start, mem.read64(current), mem.read64(line), mem.read64(column)) else if c == 34 // " - while !eof(mem.read64(current), source_len) - if peek(mem.read64(current), source, source_len) == 34 - break + while !eof(mem.read64(current), source_len) && peek(mem.read64(current), source, source_len) != 34 if peek(mem.read64(current), source, source_len) == 10 // \n mem.write64(line, mem.read64(line) + 1) mem.write64(column, 1) diff --git a/src/codegen_x86_64.rs b/src/codegen_x86_64.rs index 70e35b6..1c59dd6 100644 --- a/src/codegen_x86_64.rs +++ b/src/codegen_x86_64.rs @@ -15,6 +15,7 @@ pub struct Env { next_offset: usize, loop_begin_label: String, loop_end_label: String, + loop_continue_label: String, } impl Env { @@ -24,6 +25,7 @@ impl Env { next_offset: 8, loop_begin_label: String::new(), loop_end_label: String::new(), + loop_continue_label: String::new(), } } @@ -206,8 +208,10 @@ _builtin_environ: Stmt::While { condition, body } => { let old_loop_begin_label = env.loop_begin_label.clone(); let old_loop_end_label = env.loop_end_label.clone(); + let old_loop_continue_label = env.loop_continue_label.clone(); env.loop_begin_label = self.label(); env.loop_end_label = self.label(); + env.loop_continue_label = env.loop_begin_label.clone(); emit!(&mut self.output, "{}:", env.loop_begin_label); self.compile_expr(env, condition)?; @@ -219,6 +223,7 @@ _builtin_environ: env.loop_begin_label = old_loop_begin_label; env.loop_end_label = old_loop_end_label; + env.loop_continue_label = old_loop_continue_label; } Stmt::Function { name, @@ -277,8 +282,10 @@ _builtin_environ: } => { let old_loop_begin_label = env.loop_begin_label.clone(); let old_loop_end_label = env.loop_end_label.clone(); + let old_loop_continue_label = env.loop_continue_label.clone(); env.loop_begin_label = self.label(); env.loop_end_label = self.label(); + env.loop_continue_label = self.label(); env.push_scope(); let offset = env.define_var(var.lexeme, "i64".into()); @@ -293,6 +300,7 @@ _builtin_environ: emit!(&mut self.output, " cmp rcx, rax"); emit!(&mut self.output, " jge {}", env.loop_end_label); self.compile_stmt(env, *body)?; + emit!(&mut self.output, "{}:", env.loop_continue_label); emit!(&mut self.output, " mov rax, QWORD [rbp-{}]", offset); emit!(&mut self.output, " add rax, 1"); emit!(&mut self.output, " mov QWORD [rbp-{}], rax", offset); @@ -302,13 +310,13 @@ _builtin_environ: env.loop_begin_label = old_loop_begin_label; env.loop_end_label = old_loop_end_label; + env.loop_continue_label = old_loop_continue_label; } Stmt::Break => { emit!(&mut self.output, " jmp {}", env.loop_end_label); } Stmt::Continue => { - // TODO: skips incrementing when used in a for loop - emit!(&mut self.output, " jmp {}", env.loop_begin_label); + emit!(&mut self.output, " jmp {}", env.loop_continue_label); } Stmt::Extern(name) => { emit!(&mut self.output, "extern {}", name.lexeme); diff --git a/test.zr b/test.zr index 2e2f30e..4e3b93a 100644 --- a/test.zr +++ b/test.zr @@ -1,63 +1,63 @@ func run_test[x: str] : void - if str.equal(x, "puzzles") || str.equal(x, "raylib.zr") || str.equal(x, "x11.zr") || str.equal(x, "sqlite_todo.zr") - io.print("\033[93mSkipping ") - io.print(x) - io.println("...\033[0m") - return 0 + let build_blacklist: array = ["examples/puzzles", "examples/raylib.zr", "examples/x11.zr", "examples/sqlite_todo.zr"] + let run_blacklist: array = ["/aoc", "guess_number.zr", "tcp_server.zr"] - io.print("\033[93mBuilding ") + for i in 0..array.size(build_blacklist) + if str.equal(x, array.nth(build_blacklist, i)) + io.print("\033[93mSkipping ") + io.print(x) + io.println("...\033[0m") + return 0 + + io.print("\033[94mBuilding ") io.print(x) io.print("...\033[0m ") - let cmd: str = str.concat("./target/release/zern examples/", x) let build_start_time: i64 = os.time() - if os.shell(cmd) != 0 + if os.shell(str.concat("./target/release/zern ", x)) != 0 os.exit(1) let build_end_time: i64 = os.time() - mem.free(cmd) io.print_i64(build_end_time - build_start_time) io.println("ms") - if str.find(x, "/aoc") != -1 || str.equal(x, "guess_number.zr") || str.equal(x, "tcp_server.zr") - io.print("\033[93mSkipping ") - io.print(x) - io.println("...\033[0m") - return 0 + for i in 0..array.size(run_blacklist) + if str.find(x, array.nth(run_blacklist, i)) != -1 + io.print("\033[93mSkipping ") + io.print(x) + io.println("...\033[0m") + return 0 - io.print("\033[93mRunning ") + io.print("\033[95mRunning ") io.print(x) io.println("...\033[0m") + let run_cmd: str = "./out" + if str.equal(x, "examples/curl.zr") + run_cmd = str.concat(run_cmd, " http://example.com") + else if str.equal(x, "examples/tokenizer.zr") + run_cmd = str.concat(run_cmd, " test.zr") + let run_start_time: i64 = os.time() - if str.equal(x, "curl.zr") - if os.shell("./out http://example.com") != 0 - os.exit(1) - else if str.equal(x, "tokenizer.zr") - if os.shell("./out examples/tokenizer.zr") != 0 - os.exit(1) - else - if os.shell("./out") != 0 - os.exit(1) + if os.shell(run_cmd) != 0 + os.exit(1) let run_end_time: i64 = os.time() - io.print("\033[93mRunning ") + io.print("\033[92mRunning ") io.print(x) io.print(" took\033[0m ") io.print_i64(run_end_time - run_start_time) io.println("ms") -func main[] : i64 - os.shell("cargo build --release") - - let files: array = os.listdir("examples/") +func run_directory[dir: str] : void + let files: array = os.listdir(dir) for i in 0..array.size(files) - run_test(array.nth(files, i)) + run_test(str.concat(dir, array.nth(files, i))) array.free(files) - let puzzle_files: array = os.listdir("examples/puzzles/") - for i in 0..array.size(puzzle_files) - run_test(str.concat("puzzles/", array.nth(puzzle_files, i))) - - array.free(puzzle_files) \ No newline at end of file +func main[] : i64 + os.shell("cargo build --release") + + run_directory("examples/") + run_directory("examples/puzzles/") \ No newline at end of file