003 math builtins cross target

✓ Passing This code compiles and runs correctly.

Code

input.k

Actual

sin 0.4794 cos 0.8776 tan 0.5463
exp 2.7183 exp2 8.0000 log 2.3026 log2 3.0000 log10 3.0000
floor 1.0000 ceil 2.0000 trunc -1.0000 sqrt 1.4142 abs 3.5000
min 1.0000 max 2.5000

Expected output

✓ Zig✓ JavaScript✓ C#
sin 0.4794 cos 0.8776 tan 0.5463
exp 2.7183 exp2 8.0000 log 2.3026 log2 3.0000 log10 3.0000
floor 1.0000 ceil 2.0000 trunc -1.0000 sqrt 1.4142 abs 3.5000
min 1.0000 max 2.5000
Emitted Zig source
// Access compiler flags via the per-user compiler_env module
const CompilerEnv = @import("compiler_env").CompilerEnv;

pub const panic = if (@import("builtin").mode == .Debug)
    @import("std").debug.FullPanic(@import("std").debug.defaultPanic)
else
    @import("std").debug.simple_panic;


const __koru_bare = struct {
    extern fn posix_memalign(memptr: *?*anyopaque, alignment: usize, size: usize) c_int;
    extern fn free(ptr: ?*anyopaque) void;
    fn bareAlloc(_: *anyopaque, len: usize, alignment: @import("std").mem.Alignment, _: usize) ?[*]u8 {
        var p: ?*anyopaque = null;
        const a = @max(alignment.toByteUnits(), @sizeOf(usize));
        if (posix_memalign(&p, a, len) != 0) return null;
        return @ptrCast(p);
    }
    fn bareResize(_: *anyopaque, _: []u8, _: @import("std").mem.Alignment, _: usize, _: usize) bool { return false; }
    fn bareRemap(_: *anyopaque, _: []u8, _: @import("std").mem.Alignment, _: usize, _: usize) ?[*]u8 { return null; }
    fn bareFree(_: *anyopaque, memory: []u8, _: @import("std").mem.Alignment, _: usize) void { free(@ptrCast(memory.ptr)); }
    const vtable = @import("std").mem.Allocator.VTable{ .alloc = bareAlloc, .resize = bareResize, .remap = bareRemap, .free = bareFree };
    const allocator = @import("std").mem.Allocator{ .ptr = undefined, .vtable = &vtable };
};
const __koru_backing = if (@import("builtin").link_libc) @import("std").heap.c_allocator else if (@import("builtin").os.tag == .freestanding and !@import("builtin").cpu.arch.isWasm()) __koru_bare.allocator else @import("std").heap.page_allocator;
var __koru_leak_count: @import("std").atomic.Value(usize) = .init(0);
var __koru_par_tasks: @import("std").atomic.Value(usize) = .init(0);
const __koru_par_CAP: usize = 128;
threadlocal var __koru_par_depth: usize = 0;
const __koru_par_DEPTH_CAP: usize = 7;
var __koru_par_pool: @import("std").Thread.Pool = undefined;
var __koru_par_pool_ready: bool = false;
var __koru_par_pool_mtx: @import("std").Thread.Mutex = .{};
fn __koru_par_pool_ensure() *@import("std").Thread.Pool {
    __koru_par_pool_mtx.lock();
    defer __koru_par_pool_mtx.unlock();
    if (!__koru_par_pool_ready) {
        @import("std").Thread.Pool.init(&__koru_par_pool, .{ .allocator = @import("std").heap.smp_allocator }) catch @panic("koru: thread pool init failed");
        __koru_par_pool_ready = true;
    }
    return &__koru_par_pool;
}
fn __koru_alloc(ctx: *anyopaque, len: usize, alignment: @import("std").mem.Alignment, ret_addr: usize) ?[*]u8 {
    _ = ctx;
    const r = __koru_backing.rawAlloc(len, alignment, ret_addr);
    if (comptime @import("builtin").mode == .Debug) {
        if (r != null) _ = __koru_leak_count.fetchAdd(1, .monotonic);
    }
    return r;
}
fn __koru_resize(ctx: *anyopaque, memory: []u8, alignment: @import("std").mem.Alignment, new_len: usize, ret_addr: usize) bool {
    _ = ctx;
    return __koru_backing.rawResize(memory, alignment, new_len, ret_addr);
}
fn __koru_remap(ctx: *anyopaque, memory: []u8, alignment: @import("std").mem.Alignment, new_len: usize, ret_addr: usize) ?[*]u8 {
    _ = ctx;
    return __koru_backing.rawRemap(memory, alignment, new_len, ret_addr);
}
fn __koru_free(ctx: *anyopaque, memory: []u8, alignment: @import("std").mem.Alignment, ret_addr: usize) void {
    _ = ctx;
    __koru_backing.rawFree(memory, alignment, ret_addr);
    if (comptime @import("builtin").mode == .Debug) {
        _ = __koru_leak_count.fetchSub(1, .monotonic);
    }
}
const __koru_vtable = @import("std").mem.Allocator.VTable{ .alloc = __koru_alloc, .resize = __koru_resize, .remap = __koru_remap, .free = __koru_free };
pub fn koru_allocator() @import("std").mem.Allocator {
    return .{ .ptr = undefined, .vtable = &__koru_vtable };
}

pub inline fn __koru_intcast(comptime T: type, x: anytype) T {
    if (comptime (@import("builtin").mode == .Debug or @import("builtin").mode == .ReleaseSafe))
        return @as(T, @intCast(x));
    const dst = @typeInfo(T);
    const src = @typeInfo(@TypeOf(x));
    if (comptime (dst == .int and src == .int and dst.int.bits == src.int.bits and dst.int.signedness != src.int.signedness))
        return @as(T, @bitCast(x));
    return @as(T, @intCast(x));
}

fn __KoruPadI(comptime T: type) type {
    const V = switch (@typeInfo(T)) { .comptime_int => i64, .comptime_float => f64, else => T };
    return struct {
        v: V,
        width: usize,
        pub fn format(self: @This(), w: *@import("std").Io.Writer) @import("std").Io.Writer.Error!void {
            const rendered = @import("std").fmt.count("{d}", .{self.v});
            const pad = self.width -| rendered;
            for (0..pad) |_| try w.writeByte(' ');
            try w.print("{d}", .{self.v});
        }
    };
}
pub fn __koru_pad_i(width: usize, value: anytype) __KoruPadI(@TypeOf(value)) {
    return .{ .v = value, .width = width };
}

pub fn koru_leak_check() void {
    if (comptime @import("builtin").mode != .Debug) return;
    if (__koru_leak_count.load(.acquire) == 0) return;
    if (comptime @import("builtin").target.os.tag == .freestanding) {
        if (comptime @import("builtin").cpu.arch == .wasm32 or @import("builtin").cpu.arch == .wasm64) {
            @panic("KORU LEAK CHECK FAILED: the produced program leaked");
        } else {
            const __klc = struct { extern var stdout: ?*anyopaque; extern fn fputs(__s: [*:0]const u8, __st: ?*anyopaque) c_int; };
            var __lb: [128]u8 = undefined;
            const __lm = "KORU LEAK CHECK FAILED: allocations still outstanding at end of run: ";
            @memcpy(__lb[0..__lm.len], __lm);
            var __ln: usize = __lm.len;
            var __lv = __koru_leak_count.load(.acquire);
            var __ld: [20]u8 = undefined;
            var __lk: usize = 0;
            while (__lv > 0) : (__lk += 1) { __ld[__lk] = @intCast('0' + __lv % 10); __lv /= 10; }
            for (0..__lk) |__li| { __lb[__ln] = __ld[__lk - 1 - __li]; __ln += 1; }
            __lb[__ln] = '\n'; __ln += 1; __lb[__ln] = 0;
            _ = __klc.fputs(@as([*:0]const u8, @ptrCast(&__lb)), __klc.stdout);
            @trap();
        }
    } else {
        @import("std").debug.print("KORU LEAK CHECK FAILED: the produced program leaked (trace above)\n", .{});
        @import("std").process.exit(1);
    }
}

pub const main_module = struct {
    // >>> FLOW: tests/regression/200_COMPILER_FEATURES/230_CODEGEN/230_003_math_builtins_cross_target/input.k:8  ~std.io:print.impl()
    pub fn flow0() void {
        (struct { fn __kout(__fd: i32, __b: []const u8) void { if (@import("builtin").os.tag == .freestanding) { const __kc = struct { extern var stdout: ?*anyopaque; extern var stderr: ?*anyopaque; extern fn fputs(__s: [*:0]const u8, __st: ?*anyopaque) c_int; }; var __kt: [4096]u8 = undefined; for (0..(__b.len + __kt.len - 2) / (__kt.len - 1)) |__ki| { const __kn = @min(__kt.len - 1, __b.len - __ki * (__kt.len - 1)); @memcpy(__kt[0..__kn], __b[__ki * (__kt.len - 1)..][0..__kn]); __kt[__kn] = 0; @import("std").mem.doNotOptimizeAway(__kc.fputs(@as([*:0]const u8, @ptrCast(&__kt)), if (__fd == 2) __kc.stderr else __kc.stdout)); } } else { @import("std").mem.doNotOptimizeAway(@import("std").posix.write(__fd, __b) catch @as(usize, 0)); } } fn __kw(comptime __f: []const u8, __a: anytype) void { var __kb: [65536]u8 = undefined; const __ks = @import("std").fmt.bufPrint(&__kb, __f, __a) catch __kb[0..0]; __kout(1, __ks); } }).__kw("sin {d:.4} cos {d:.4} tan {d:.4}\n", .{@sin(0.5), @cos(0.5), @tan(0.5)});
    }
    // >>> FLOW: tests/regression/200_COMPILER_FEATURES/230_CODEGEN/230_003_math_builtins_cross_target/input.k:9  ~std.io:print.impl()
    pub fn flow1() void {
        (struct { fn __kout(__fd: i32, __b: []const u8) void { if (@import("builtin").os.tag == .freestanding) { const __kc = struct { extern var stdout: ?*anyopaque; extern var stderr: ?*anyopaque; extern fn fputs(__s: [*:0]const u8, __st: ?*anyopaque) c_int; }; var __kt: [4096]u8 = undefined; for (0..(__b.len + __kt.len - 2) / (__kt.len - 1)) |__ki| { const __kn = @min(__kt.len - 1, __b.len - __ki * (__kt.len - 1)); @memcpy(__kt[0..__kn], __b[__ki * (__kt.len - 1)..][0..__kn]); __kt[__kn] = 0; @import("std").mem.doNotOptimizeAway(__kc.fputs(@as([*:0]const u8, @ptrCast(&__kt)), if (__fd == 2) __kc.stderr else __kc.stdout)); } } else { @import("std").mem.doNotOptimizeAway(@import("std").posix.write(__fd, __b) catch @as(usize, 0)); } } fn __kw(comptime __f: []const u8, __a: anytype) void { var __kb: [65536]u8 = undefined; const __ks = @import("std").fmt.bufPrint(&__kb, __f, __a) catch __kb[0..0]; __kout(1, __ks); } }).__kw("exp {d:.4} exp2 {d:.4} log {d:.4} log2 {d:.4} log10 {d:.4}\n", .{@exp(1.0), @exp2(3.0), @log(10.0), @log2(8.0), @log10(1000.0)});
    }
    // >>> FLOW: tests/regression/200_COMPILER_FEATURES/230_CODEGEN/230_003_math_builtins_cross_target/input.k:10  ~std.io:print.impl()
    pub fn flow2() void {
        (struct { fn __kout(__fd: i32, __b: []const u8) void { if (@import("builtin").os.tag == .freestanding) { const __kc = struct { extern var stdout: ?*anyopaque; extern var stderr: ?*anyopaque; extern fn fputs(__s: [*:0]const u8, __st: ?*anyopaque) c_int; }; var __kt: [4096]u8 = undefined; for (0..(__b.len + __kt.len - 2) / (__kt.len - 1)) |__ki| { const __kn = @min(__kt.len - 1, __b.len - __ki * (__kt.len - 1)); @memcpy(__kt[0..__kn], __b[__ki * (__kt.len - 1)..][0..__kn]); __kt[__kn] = 0; @import("std").mem.doNotOptimizeAway(__kc.fputs(@as([*:0]const u8, @ptrCast(&__kt)), if (__fd == 2) __kc.stderr else __kc.stdout)); } } else { @import("std").mem.doNotOptimizeAway(@import("std").posix.write(__fd, __b) catch @as(usize, 0)); } } fn __kw(comptime __f: []const u8, __a: anytype) void { var __kb: [65536]u8 = undefined; const __ks = @import("std").fmt.bufPrint(&__kb, __f, __a) catch __kb[0..0]; __kout(1, __ks); } }).__kw("floor {d:.4} ceil {d:.4} trunc {d:.4} sqrt {d:.4} abs {d:.4}\n", .{@floor(1.7), @ceil(1.2), @trunc(-1.7), @sqrt(2.0), @abs(-3.5)});
    }
    // >>> FLOW: tests/regression/200_COMPILER_FEATURES/230_CODEGEN/230_003_math_builtins_cross_target/input.k:11  ~std.io:print.impl()
    pub fn flow3() void {
        (struct { fn __kout(__fd: i32, __b: []const u8) void { if (@import("builtin").os.tag == .freestanding) { const __kc = struct { extern var stdout: ?*anyopaque; extern var stderr: ?*anyopaque; extern fn fputs(__s: [*:0]const u8, __st: ?*anyopaque) c_int; }; var __kt: [4096]u8 = undefined; for (0..(__b.len + __kt.len - 2) / (__kt.len - 1)) |__ki| { const __kn = @min(__kt.len - 1, __b.len - __ki * (__kt.len - 1)); @memcpy(__kt[0..__kn], __b[__ki * (__kt.len - 1)..][0..__kn]); __kt[__kn] = 0; @import("std").mem.doNotOptimizeAway(__kc.fputs(@as([*:0]const u8, @ptrCast(&__kt)), if (__fd == 2) __kc.stderr else __kc.stdout)); } } else { @import("std").mem.doNotOptimizeAway(@import("std").posix.write(__fd, __b) catch @as(usize, 0)); } } fn __kw(comptime __f: []const u8, __a: anytype) void { var __kb: [65536]u8 = undefined; const __ks = @import("std").fmt.bufPrint(&__kb, __f, __a) catch __kb[0..0]; __kout(1, __ks); } }).__kw("min {d:.4} max {d:.4}\n", .{@min(1.0, 2.5), @max(1.0, 2.5)});
    }
    pub fn koru_start_flow() void {
        const result_0 = koru_koru.start_event.handler(.{  });
        const result_0_done = result_0.done;
        _ = &result_0_done;
    }
    pub fn koru_end_flow() void {
        const result_0 = koru_koru.end_event.handler(.{  });
        const result_0_done = result_0.done;
        _ = &result_0_done;
    }
};

pub const koru_koru = struct {
    pub const start_event = struct {
        pub const Input = struct {
        };
        pub const Output = union(enum(u8)) {
            done: struct {
            },
        };
        pub fn handler(__koru_event_input: @This().Input) @This().Output {
            _ = &__koru_event_input;
            return .{ .done = .{} };
        }
    };
    pub const end_event = struct {
        pub const Input = struct {
        };
        pub const Output = union(enum(u8)) {
            done: struct {
            },
        };
        pub fn handler(__koru_event_input: @This().Input) @This().Output {
            _ = &__koru_event_input;
            return .{ .done = .{} };
        }
    };
};
pub fn main() void {
    main_module.koru_start_flow();
    main_module.flow0();
    main_module.flow1();
    main_module.flow2();
    main_module.flow3();
    main_module.koru_end_flow();
    if (comptime @import("builtin").mode == .Debug) koru_leak_check();
}

test {
    @import("std").testing.refAllDeclsRecursive(@This());
}
Emitted C# source
static class main_module {
  public static void __koru_stdout_write(object s) => global::System.Console.Out.Write(s);
  public static void __koru_stderr_write(object s) => global::System.Console.Error.Write(s);
  // The mutable handle carrier — `*String`-style resources are
  // `new __KoruBox { data = … }` because C# anonymous types are
  // read-only: `s.data = …` (std/string append/clear, handle
  // mutation generally) needs a settable member. `object`, not
  // `dynamic`: the field is storage — every `x.data` read reaches
  // it through a dynamic-typed handle (`*T` Input fields, the
  // `dynamic` borrow locals below), so the member itself only
  // needs to hold the value, and `object` keeps the DLR out of
  // the store/load path.
  public class __KoruBox { public object data; }
  // Textification for `{{ … }}` operands: C# bool ToStrings as
  // `True` where Koru prints `true`, and the operand's static type
  // is unknown at this boundary — a `(x) is bool` inline test would
  // be a compile error on statically-typed operands instead. Generic
  // on purpose: `dynamic` boxed every value-type operand — measured
  // ~1s/10M elements on 012_threat_scanner — while T specializes to
  // the operand's own ToString() with no box.
  public static string __koru_str<T>(T v) => v is bool b ? (b ? "true" : "false") : v?.ToString();
  public static class std_io_print_impl_event {
    public struct Input {
      public string expr;
    }
    public static object handler(Input __koru_input) {
      throw new global::System.Exception("std.io:impl has no C# implementation — its body resolves only to a non-cs target (|zig / [comptime]), directly or through a callee");
    }
  }
  public static class koru_start_event {
    public struct Input {
    }
    public struct Output {
      public string tag;
      public object done;
    }
    public static Output handler(Input __koru_input) => new Output { tag = "done" };
  }
  public static class koru_end_event {
    public struct Input {
    }
    public struct Output {
      public string tag;
      public object done;
    }
    public static Output handler(Input __koru_input) => new Output { tag = "done" };
  }
  public static void flow0() {
__koru_stdout_write("sin " + (global::System.Math.Sin(0.5)).ToString("F4", global::System.Globalization.CultureInfo.InvariantCulture) + " cos " + (global::System.Math.Cos(0.5)).ToString("F4", global::System.Globalization.CultureInfo.InvariantCulture) + " tan " + (global::System.Math.Tan(0.5)).ToString("F4", global::System.Globalization.CultureInfo.InvariantCulture) + "\n");
  }
  public static void flow1() {
__koru_stdout_write("exp " + (global::System.Math.Exp(1.0)).ToString("F4", global::System.Globalization.CultureInfo.InvariantCulture) + " exp2 " + (global::System.Math.Pow(2, 3.0)).ToString("F4", global::System.Globalization.CultureInfo.InvariantCulture) + " log " + (global::System.Math.Log(10.0)).ToString("F4", global::System.Globalization.CultureInfo.InvariantCulture) + " log2 " + (global::System.Math.Log2(8.0)).ToString("F4", global::System.Globalization.CultureInfo.InvariantCulture) + " log10 " + (global::System.Math.Log10(1000.0)).ToString("F4", global::System.Globalization.CultureInfo.InvariantCulture) + "\n");
  }
  public static void flow2() {
__koru_stdout_write("floor " + (global::System.Math.Floor(1.7)).ToString("F4", global::System.Globalization.CultureInfo.InvariantCulture) + " ceil " + (global::System.Math.Ceiling(1.2)).ToString("F4", global::System.Globalization.CultureInfo.InvariantCulture) + " trunc " + (global::System.Math.Truncate(-1.7)).ToString("F4", global::System.Globalization.CultureInfo.InvariantCulture) + " sqrt " + (global::System.Math.Sqrt(2.0)).ToString("F4", global::System.Globalization.CultureInfo.InvariantCulture) + " abs " + (global::System.Math.Abs(-3.5)).ToString("F4", global::System.Globalization.CultureInfo.InvariantCulture) + "\n");
  }
  public static void flow3() {
__koru_stdout_write("min " + (global::System.Math.Min(1.0, 2.5)).ToString("F4", global::System.Globalization.CultureInfo.InvariantCulture) + " max " + (global::System.Math.Max(1.0, 2.5)).ToString("F4", global::System.Globalization.CultureInfo.InvariantCulture) + "\n");
  }
  public static void flow4() {
    main_module.koru_start_event.handler(new koru_start_event.Input { });
  }
  public static void flow5() {
    main_module.koru_end_event.handler(new koru_end_event.Input { });
  }
}

static class Program {
  static void Main() {
    main_module.flow4();
    main_module.flow0();
    main_module.flow1();
    main_module.flow2();
    main_module.flow3();
    main_module.flow5();
  }
}

Flows

flow ~print click a branch to expand · @labels scroll to their anchor
print (expr: "sin {{ @sin(0.5):d:.4 }} cos {{ @cos(0.5):d:.4 }} tan {{ @tan(0.5):d:.4 }}\n")
flow ~print click a branch to expand · @labels scroll to their anchor
print (expr: "exp {{ @exp(1.0):d:.4 }} exp2 {{ @exp2(3.0):d:.4 }} log {{ @log(10.0):d:.4 }} log2 {{ @log2(8.0):d:.4 }} log10 {{ @log10(1000.0):d:.4 }}\n")
flow ~print click a branch to expand · @labels scroll to their anchor
print (expr: "floor {{ @floor(1.7):d:.4 }} ceil {{ @ceil(1.2):d:.4 }} trunc {{ @trunc(-1.7):d:.4 }} sqrt {{ @sqrt(2.0):d:.4 }} abs {{ @abs(-3.5):d:.4 }}\n")
flow ~print click a branch to expand · @labels scroll to their anchor
print (expr: "min {{ @min(1.0, 2.5):d:.4 }} max {{ @max(1.0, 2.5):d:.4 }}\n")

Test Configuration

MUST_RUN LANGUAGES: zig js cs