diff --git a/src/codegen/zig/mod.rs b/src/codegen/zig/mod.rs index e822cff..346ea51 100644 --- a/src/codegen/zig/mod.rs +++ b/src/codegen/zig/mod.rs @@ -208,6 +208,7 @@ impl ZigBackend { let mut out = String::new(); if needs_std { out.push_str("const std = @import(\"std\");\n"); + out.push_str("const __zyre_runtime = @import(\"zyre_runtime.zig\");\n"); } for (name, path) in &user_imports { out.push_str(&format!("const {} = @import(\"{}\");\n", name, path)); @@ -291,6 +292,8 @@ impl ZigBackend { if !body_stmts.is_empty() && !has_explicit_main { let needs_alloc = self.uses_allocator(&body_stmts); out.push_str("pub fn main() !void {\n"); + out.push_str(" try __zyre_runtime.Output.init();\n"); + out.push_str(" defer __zyre_runtime.Output.restore();\n"); out.push_str(&Self::gen_arena_setup(needs_alloc)); for stmt in &body_stmts { out.push_str(&self.gen_stmt(stmt, 1)); @@ -350,6 +353,8 @@ impl ZigBackend { let mut out = format!("{}fn {}({}) {} {{\n", pub_prefix, f.name, params_str, ret); if f.name == "main" { + out.push_str(" try __zyre_runtime.Output.init();\n"); + out.push_str(" defer __zyre_runtime.Output.restore();\n"); out.push_str(&Self::gen_arena_setup(needs_alloc)); } diff --git a/src/commands/mod.rs b/src/commands/mod.rs index 24aaeec..7104530 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -70,9 +70,13 @@ pub fn collect_zy_imports( result } +const ZYRE_RUNTIME: &str = include_str!("../runtime/zyre_runtime.zig"); + /// Generates a .zig file in the cache from a pre-parsed AST. Returns (stem, zig_path). pub fn emit_zig(input_path: &str, ast: &crate::parser::Program) -> (String, String) { std::fs::create_dir_all("zyre-cache").unwrap(); + std::fs::write("zyre-cache/zyre_runtime.zig", ZYRE_RUNTIME) + .unwrap_or_else(|e| panic!("Failed to write zyre_runtime.zig: {}", e)); let mut visited = std::collections::HashSet::new(); let source_dir = Path::new(input_path).parent().unwrap_or(Path::new(".")); diff --git a/src/runtime/zyre_runtime.zig b/src/runtime/zyre_runtime.zig new file mode 100644 index 0000000..b5f8913 --- /dev/null +++ b/src/runtime/zyre_runtime.zig @@ -0,0 +1,55 @@ +const std = @import("std"); +const builtin = @import("builtin"); + +const is_windows = builtin.os.tag == .windows; + +pub const Output = struct { + pub fn init() !void { + if (comptime is_windows) { + try WindowsOutput.init(); + } + } + pub fn restore() void { + if (comptime is_windows) { + WindowsOutput.restore(); + } + } +}; + +const WindowsOutput = struct { + const win = std.os.windows; + const k32 = win.kernel32; + var console_output_cp: c_uint = @as(u32, 0); + + fn setAbortSignalHandler(comptime handler: *const fn () void) !void { + const handler_routine = struct { + fn handler_routine(dwCtrlType: win.DWORD) callconv(.winapi) win.BOOL { + if (dwCtrlType == win.CTRL_C_EVENT) { + handler(); + return win.TRUE; + } else { + return win.FALSE; + } + } + }.handler_routine; + + try win.SetConsoleCtrlHandler(handler_routine, true); + } + + fn abortSignalHandler() void { + restore(); + std.process.exit(130); + } + + pub fn init() !void { + const CP_UTF8 = 65001; + console_output_cp = k32.GetConsoleOutputCP(); + try setAbortSignalHandler(abortSignalHandler); + _ = k32.SetConsoleOutputCP(CP_UTF8); + } + + pub fn restore() void { + if (console_output_cp != 0) + _ = k32.SetConsoleOutputCP(console_output_cp); + } +}; diff --git a/src/tests/snapshots/zyre__tests__snapshots__codegen_snapshots@alloc_propagate.zy.snap b/src/tests/snapshots/zyre__tests__snapshots__codegen_snapshots@alloc_propagate.zy.snap index 5b82289..be0fb1b 100644 --- a/src/tests/snapshots/zyre__tests__snapshots__codegen_snapshots@alloc_propagate.zy.snap +++ b/src/tests/snapshots/zyre__tests__snapshots__codegen_snapshots@alloc_propagate.zy.snap @@ -1,9 +1,11 @@ --- source: src/tests/snapshots.rs +assertion_line: 10 expression: output input_file: src/tests/fixtures/alloc_propagate.zy --- const std = @import("std"); +const __zyre_runtime = @import("zyre_runtime.zig"); fn __zyre_print(val: anytype) void { if (comptime @typeInfo(@TypeOf(val)) == .pointer) { @@ -18,6 +20,8 @@ fn readIt(__zyre_allocator: std.mem.Allocator) ![]const u8 { } pub fn main() !void { + try __zyre_runtime.Output.init(); + defer __zyre_runtime.Output.restore(); var __zyre_arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); defer __zyre_arena.deinit(); const __zyre_allocator = __zyre_arena.allocator(); diff --git a/src/tests/snapshots/zyre__tests__snapshots__codegen_snapshots@array.zy.snap b/src/tests/snapshots/zyre__tests__snapshots__codegen_snapshots@array.zy.snap index 6d8256d..b2ae629 100644 --- a/src/tests/snapshots/zyre__tests__snapshots__codegen_snapshots@array.zy.snap +++ b/src/tests/snapshots/zyre__tests__snapshots__codegen_snapshots@array.zy.snap @@ -1,9 +1,11 @@ --- source: src/tests/snapshots.rs +assertion_line: 10 expression: output input_file: src/tests/fixtures/array.zy --- const std = @import("std"); +const __zyre_runtime = @import("zyre_runtime.zig"); fn __zyre_print(val: anytype) void { if (comptime @typeInfo(@TypeOf(val)) == .pointer) { @@ -14,6 +16,8 @@ fn __zyre_print(val: anytype) void { } pub fn main() !void { + try __zyre_runtime.Output.init(); + defer __zyre_runtime.Output.restore(); var __zyre_arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); defer __zyre_arena.deinit(); const __zyre_allocator = __zyre_arena.allocator(); diff --git a/src/tests/snapshots/zyre__tests__snapshots__codegen_snapshots@enum_decl.zy.snap b/src/tests/snapshots/zyre__tests__snapshots__codegen_snapshots@enum_decl.zy.snap index 602d306..f561f84 100644 --- a/src/tests/snapshots/zyre__tests__snapshots__codegen_snapshots@enum_decl.zy.snap +++ b/src/tests/snapshots/zyre__tests__snapshots__codegen_snapshots@enum_decl.zy.snap @@ -1,9 +1,11 @@ --- source: src/tests/snapshots.rs +assertion_line: 10 expression: output input_file: src/tests/fixtures/enum_decl.zy --- const std = @import("std"); +const __zyre_runtime = @import("zyre_runtime.zig"); fn __zyre_print(val: anytype) void { if (comptime @typeInfo(@TypeOf(val)) == .pointer) { @@ -30,6 +32,8 @@ fn describe(d: Direction) void { } pub fn main() !void { + try __zyre_runtime.Output.init(); + defer __zyre_runtime.Output.restore(); var __zyre_arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); defer __zyre_arena.deinit(); const __zyre_allocator = __zyre_arena.allocator(); diff --git a/src/tests/snapshots/zyre__tests__snapshots__codegen_snapshots@export_const.zy.snap b/src/tests/snapshots/zyre__tests__snapshots__codegen_snapshots@export_const.zy.snap index a49834e..10ff8f7 100644 --- a/src/tests/snapshots/zyre__tests__snapshots__codegen_snapshots@export_const.zy.snap +++ b/src/tests/snapshots/zyre__tests__snapshots__codegen_snapshots@export_const.zy.snap @@ -1,9 +1,11 @@ --- source: src/tests/snapshots.rs +assertion_line: 10 expression: output input_file: src/tests/fixtures/export_const.zy --- const std = @import("std"); +const __zyre_runtime = @import("zyre_runtime.zig"); fn __zyre_print(val: anytype) void { if (comptime @typeInfo(@TypeOf(val)) == .pointer) { @@ -18,6 +20,8 @@ const b = 3; pub const c = (a * b); pub fn main() !void { + try __zyre_runtime.Output.init(); + defer __zyre_runtime.Output.restore(); var __zyre_arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); defer __zyre_arena.deinit(); const __zyre_allocator = __zyre_arena.allocator(); diff --git a/src/tests/snapshots/zyre__tests__snapshots__codegen_snapshots@fn_call.zy.snap b/src/tests/snapshots/zyre__tests__snapshots__codegen_snapshots@fn_call.zy.snap index 9b80611..ccc1612 100644 --- a/src/tests/snapshots/zyre__tests__snapshots__codegen_snapshots@fn_call.zy.snap +++ b/src/tests/snapshots/zyre__tests__snapshots__codegen_snapshots@fn_call.zy.snap @@ -1,9 +1,11 @@ --- source: src/tests/snapshots.rs +assertion_line: 10 expression: output input_file: src/tests/fixtures/fn_call.zy --- const std = @import("std"); +const __zyre_runtime = @import("zyre_runtime.zig"); fn __zyre_print(val: anytype) void { if (comptime @typeInfo(@TypeOf(val)) == .pointer) { @@ -18,6 +20,8 @@ fn add(a: i32, b: i32) i32 { } pub fn main() !void { + try __zyre_runtime.Output.init(); + defer __zyre_runtime.Output.restore(); var __zyre_arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); defer __zyre_arena.deinit(); const __zyre_allocator = __zyre_arena.allocator(); diff --git a/src/tests/snapshots/zyre__tests__snapshots__codegen_snapshots@if_stmt.zy.snap b/src/tests/snapshots/zyre__tests__snapshots__codegen_snapshots@if_stmt.zy.snap index 69e6b63..17492d4 100644 --- a/src/tests/snapshots/zyre__tests__snapshots__codegen_snapshots@if_stmt.zy.snap +++ b/src/tests/snapshots/zyre__tests__snapshots__codegen_snapshots@if_stmt.zy.snap @@ -1,9 +1,11 @@ --- source: src/tests/snapshots.rs +assertion_line: 10 expression: output input_file: src/tests/fixtures/if_stmt.zy --- const std = @import("std"); +const __zyre_runtime = @import("zyre_runtime.zig"); fn __zyre_print(val: anytype) void { if (comptime @typeInfo(@TypeOf(val)) == .pointer) { @@ -14,6 +16,8 @@ fn __zyre_print(val: anytype) void { } pub fn main() !void { + try __zyre_runtime.Output.init(); + defer __zyre_runtime.Output.restore(); var __zyre_arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); defer __zyre_arena.deinit(); const __zyre_allocator = __zyre_arena.allocator(); diff --git a/src/tests/snapshots/zyre__tests__snapshots__codegen_snapshots@print_int.zy.snap b/src/tests/snapshots/zyre__tests__snapshots__codegen_snapshots@print_int.zy.snap index 1a3be9c..f90aac3 100644 --- a/src/tests/snapshots/zyre__tests__snapshots__codegen_snapshots@print_int.zy.snap +++ b/src/tests/snapshots/zyre__tests__snapshots__codegen_snapshots@print_int.zy.snap @@ -1,9 +1,11 @@ --- source: src/tests/snapshots.rs +assertion_line: 10 expression: output input_file: src/tests/fixtures/print_int.zy --- const std = @import("std"); +const __zyre_runtime = @import("zyre_runtime.zig"); fn __zyre_print(val: anytype) void { if (comptime @typeInfo(@TypeOf(val)) == .pointer) { @@ -14,6 +16,8 @@ fn __zyre_print(val: anytype) void { } pub fn main() !void { + try __zyre_runtime.Output.init(); + defer __zyre_runtime.Output.restore(); var __zyre_arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); defer __zyre_arena.deinit(); const __zyre_allocator = __zyre_arena.allocator(); diff --git a/src/tests/snapshots/zyre__tests__snapshots__codegen_snapshots@print_str.zy.snap b/src/tests/snapshots/zyre__tests__snapshots__codegen_snapshots@print_str.zy.snap index dd4d8c0..f6044e2 100644 --- a/src/tests/snapshots/zyre__tests__snapshots__codegen_snapshots@print_str.zy.snap +++ b/src/tests/snapshots/zyre__tests__snapshots__codegen_snapshots@print_str.zy.snap @@ -1,9 +1,11 @@ --- source: src/tests/snapshots.rs +assertion_line: 10 expression: output input_file: src/tests/fixtures/print_str.zy --- const std = @import("std"); +const __zyre_runtime = @import("zyre_runtime.zig"); fn __zyre_print(val: anytype) void { if (comptime @typeInfo(@TypeOf(val)) == .pointer) { @@ -14,6 +16,8 @@ fn __zyre_print(val: anytype) void { } pub fn main() !void { + try __zyre_runtime.Output.init(); + defer __zyre_runtime.Output.restore(); var __zyre_arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); defer __zyre_arena.deinit(); const __zyre_allocator = __zyre_arena.allocator(); diff --git a/src/tests/snapshots/zyre__tests__snapshots__codegen_snapshots@read_text_file.zy.snap b/src/tests/snapshots/zyre__tests__snapshots__codegen_snapshots@read_text_file.zy.snap index 5bc324b..229dd12 100644 --- a/src/tests/snapshots/zyre__tests__snapshots__codegen_snapshots@read_text_file.zy.snap +++ b/src/tests/snapshots/zyre__tests__snapshots__codegen_snapshots@read_text_file.zy.snap @@ -1,9 +1,11 @@ --- source: src/tests/snapshots.rs +assertion_line: 10 expression: output input_file: src/tests/fixtures/read_text_file.zy --- const std = @import("std"); +const __zyre_runtime = @import("zyre_runtime.zig"); fn __zyre_print(val: anytype) void { if (comptime @typeInfo(@TypeOf(val)) == .pointer) { @@ -14,6 +16,8 @@ fn __zyre_print(val: anytype) void { } pub fn main() !void { + try __zyre_runtime.Output.init(); + defer __zyre_runtime.Output.restore(); var __zyre_arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); defer __zyre_arena.deinit(); const __zyre_allocator = __zyre_arena.allocator(); diff --git a/src/tests/snapshots/zyre__tests__snapshots__codegen_snapshots@struct_decl.zy.snap b/src/tests/snapshots/zyre__tests__snapshots__codegen_snapshots@struct_decl.zy.snap index df66cdd..594b6ad 100644 --- a/src/tests/snapshots/zyre__tests__snapshots__codegen_snapshots@struct_decl.zy.snap +++ b/src/tests/snapshots/zyre__tests__snapshots__codegen_snapshots@struct_decl.zy.snap @@ -1,9 +1,11 @@ --- source: src/tests/snapshots.rs +assertion_line: 10 expression: output input_file: src/tests/fixtures/struct_decl.zy --- const std = @import("std"); +const __zyre_runtime = @import("zyre_runtime.zig"); fn __zyre_print(val: anytype) void { if (comptime @typeInfo(@TypeOf(val)) == .pointer) { @@ -23,6 +25,8 @@ fn getX(p: Point) i32 { } pub fn main() !void { + try __zyre_runtime.Output.init(); + defer __zyre_runtime.Output.restore(); var __zyre_arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); defer __zyre_arena.deinit(); const __zyre_allocator = __zyre_arena.allocator(); diff --git a/src/tests/snapshots/zyre__tests__snapshots__codegen_snapshots@switch_stmt.zy.snap b/src/tests/snapshots/zyre__tests__snapshots__codegen_snapshots@switch_stmt.zy.snap index bfe8994..dd21503 100644 --- a/src/tests/snapshots/zyre__tests__snapshots__codegen_snapshots@switch_stmt.zy.snap +++ b/src/tests/snapshots/zyre__tests__snapshots__codegen_snapshots@switch_stmt.zy.snap @@ -1,9 +1,11 @@ --- source: src/tests/snapshots.rs +assertion_line: 10 expression: output input_file: src/tests/fixtures/switch_stmt.zy --- const std = @import("std"); +const __zyre_runtime = @import("zyre_runtime.zig"); fn __zyre_print(val: anytype) void { if (comptime @typeInfo(@TypeOf(val)) == .pointer) { @@ -22,6 +24,8 @@ fn check(n: i32) void { } pub fn main() !void { + try __zyre_runtime.Output.init(); + defer __zyre_runtime.Output.restore(); var __zyre_arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); defer __zyre_arena.deinit(); const __zyre_allocator = __zyre_arena.allocator(); diff --git a/src/tests/snapshots/zyre__tests__snapshots__codegen_snapshots@while_loop.zy.snap b/src/tests/snapshots/zyre__tests__snapshots__codegen_snapshots@while_loop.zy.snap index 04b4a3a..af8cf4a 100644 --- a/src/tests/snapshots/zyre__tests__snapshots__codegen_snapshots@while_loop.zy.snap +++ b/src/tests/snapshots/zyre__tests__snapshots__codegen_snapshots@while_loop.zy.snap @@ -1,9 +1,11 @@ --- source: src/tests/snapshots.rs +assertion_line: 10 expression: output input_file: src/tests/fixtures/while_loop.zy --- const std = @import("std"); +const __zyre_runtime = @import("zyre_runtime.zig"); fn __zyre_print(val: anytype) void { if (comptime @typeInfo(@TypeOf(val)) == .pointer) { @@ -14,6 +16,8 @@ fn __zyre_print(val: anytype) void { } pub fn main() !void { + try __zyre_runtime.Output.init(); + defer __zyre_runtime.Output.restore(); var __zyre_arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); defer __zyre_arena.deinit(); const __zyre_allocator = __zyre_arena.allocator();