✗
Failing This test is currently failing.
Failed: backend-exec
Error Details
install
Failure Output
Showing last 10 of 26 lines
error: the following command failed with 1 compilation errors:
/opt/homebrew/Cellar/zig/0.15.2_1/bin/zig build-exe -ODebug --dep koru_parser --dep koru_ast=ast --dep koru_errors=errors --dep ast --dep flow_parser --dep liquid -Mroot=/Users/larsde/src/koru/tests/regression/400_RUNTIME_FEATURES/430_RUNTIME/430_036_interpreter_for_loop/output_emitted.zig -ODebug --dep ast --dep lexer --dep errors --dep type_registry --dep expression_parser --dep union_collector --dep module_resolver -Mkoru_parser=/usr/local/lib/koru/src/parser.zig -ODebug --dep errors -Mast=/usr/local/lib/koru/src/ast.zig -ODebug -Merrors=/usr/local/lib/koru/src/errors.zig -ODebug --dep ast --dep lexer --dep errors --dep expression_parser -Mflow_parser=/usr/local/lib/koru/src/flow_parser.zig -ODebug -Mliquid=/usr/local/lib/koru/src/liquid.zig -ODebug -Mlexer=/usr/local/lib/koru/src/lexer.zig -ODebug --dep ast --dep log -Mtype_registry=/usr/local/lib/koru/src/type_registry.zig -ODebug --dep lexer --dep ast -Mexpression_parser=/usr/local/lib/koru/src/expression_parser.zig -ODebug --dep ast -Munion_collector=/usr/local/lib/koru/src/union_collector.zig -ODebug --dep config --dep log -Mmodule_resolver=/usr/local/lib/koru/src/module_resolver.zig -ODebug -Mlog=/usr/local/lib/koru/src/log.zig -ODebug --dep log -Mconfig=/usr/local/lib/koru/src/config.zig --cache-dir .zig-cache --global-cache-dir /Users/larsde/.cache/zig --name output --zig-lib-dir /opt/homebrew/Cellar/zig/0.15.2_1/lib/zig/ --listen=-
Build Summary: 0/3 steps succeeded; 1 failed
install transitive failure
+- install output transitive failure
+- compile exe output Debug native 1 errors
error: the following build command failed with exit code 1:
.zig-cache/o/ab7734ce170e335c623eadd760da5c97/build /opt/homebrew/Cellar/zig/0.15.2_1/bin/zig /opt/homebrew/Cellar/zig/0.15.2_1/lib/zig /Users/larsde/src/koru/tests/regression/400_RUNTIME_FEATURES/430_RUNTIME/430_036_interpreter_for_loop .zig-cache /Users/larsde/.cache/zig --seed 0x85fe13ce -Z9d424370de9c4946 Code
// Test: Interpreter for loop
//
// Tests that ~for(0..N) | each i |> body | done |> ... works
~import "$std/runtime"
~import "$std/interpreter"
~import "$std/io"
const std = @import("std");
// Event that prints a number
~pub event print_num { n: []const u8 }
| printed
~proc print_num {
std.debug.print("[print_num] n = {s}\n", .{n});
return .{ .printed = .{} };
}
// Register events including control flow
~std.runtime:register(scope: "test") {
for
print_num
}
// Test flow: loop 3 times, print each iteration
const TEST_FLOW =
\\~for(0..3)
\\| each i |> print_num(n: i)
\\| done |> result { status: "complete" }
;
~std.interpreter:run(source: TEST_FLOW, dispatcher: dispatch_test)
| result r |> std.io:print.ln("Result: {{ r.value.branch:s }}")
| exhausted e |> std.io:print.ln("Exhausted: {{ e.last_event:s }}")
| parse_error e |> std.io:print.ln("Parse error: {{ e.message:s }}")
| validation_error e |> std.io:print.ln("Validation error: {{ e.message:s }}")
| dispatch_error e |> std.io:print.ln("Dispatch error: {{ e.message:s }}")
Imported Files
// HONEST INTERPRETER BENCHMARK
//
// Task: Sum numbers 0..99 using for loop
// Measure: Parse once, execute N times, report per-execution time
// Compare: Python doing the same thing
~import "$std/runtime"
~import "$std/interpreter"
const std = @import("std");
// ============================================================================
// Events for computation
// ============================================================================
~pub event add { a: []const u8, b: []const u8 }
| sum []const u8
~proc add {
const a_int = std.fmt.parseInt(i64, a, 10) catch 0;
const b_int = std.fmt.parseInt(i64, b, 10) catch 0;
const result_int = a_int + b_int;
var buf: [32]u8 = undefined;
const result_str = std.fmt.bufPrint(&buf, "{d}", .{result_int}) catch "0";
return .{ .sum = result_str };
}
~pub event init_sum {}
| value []const u8
~proc init_sum {
return .{ .value = "0" };
}
// Register events including for
~std.runtime:register(scope: "bench") {
for
add
init_sum
}
// The benchmark flow: sum 0..100
const BENCH_FLOW =
\\~for(0..100)
\\| each i |> add(a: "0", b: i)
\\| done |> result { status: "complete" }
;
// Simple flow for comparison (no loop)
const SIMPLE_FLOW =
\\~add(a: "21", b: "21")
;
// ============================================================================
// BENCHMARK
// ============================================================================
pub fn main() void {
const koru_parser = @import("koru_parser");
std.debug.print("\n", .{});
std.debug.print("============================================================\n", .{});
std.debug.print("HONEST INTERPRETER BENCHMARK\n", .{});
std.debug.print("============================================================\n\n", .{});
const ITERATIONS = 1000;
// ========================================================================
// BENCHMARK 1: Simple dispatch (no loop) - parse once, dispatch N times
// ========================================================================
std.debug.print("[1] SIMPLE DISPATCH: ~add(a: \"21\", b: \"21\")\n", .{});
std.debug.print(" Iterations: {d}\n", .{ITERATIONS});
{
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
defer arena.deinit();
const allocator = arena.allocator();
// Parse once
var parser = koru_parser.Parser.init(allocator, SIMPLE_FLOW, "bench", &[_][]const u8{}, null) catch {
std.debug.print(" ERROR: Parser init failed\n", .{});
return;
};
defer parser.deinit();
const parse_result = parser.parse() catch {
std.debug.print(" ERROR: Parse failed\n", .{});
return;
};
// Find the flow
var inv_ptr: ?*const @import("ast").Invocation = null;
for (parse_result.source_file.items) |*item| {
if (item.* == .flow) {
inv_ptr = &item.flow.invocation;
break;
}
}
if (inv_ptr == null) {
std.debug.print(" ERROR: No flow found\n", .{});
return;
}
// Warm up
for (0..10) |_| {
var result: koru_std.runtime.DispatchResult = undefined;
dispatch_bench(inv_ptr.?, &result) catch continue;
}
// Time it
const start = std.time.nanoTimestamp();
for (0..ITERATIONS) |_| {
var result: koru_std.runtime.DispatchResult = undefined;
dispatch_bench(inv_ptr.?, &result) catch continue;
}
const end = std.time.nanoTimestamp();
const total_ns = end - start;
const per_iter_ns = @divTrunc(total_ns, ITERATIONS);
std.debug.print(" Total: {d} ms\n", .{@divTrunc(total_ns, 1_000_000)});
std.debug.print(" Per dispatch: {d} ns\n", .{per_iter_ns});
}
std.debug.print("\n", .{});
// ========================================================================
// BENCHMARK 2: Full interpreter with for loop
// ========================================================================
std.debug.print("[2] FULL INTERPRETER: ~for(0..100) with adds\n", .{});
std.debug.print(" Iterations: {d}\n", .{ITERATIONS});
{
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
defer arena.deinit();
const allocator = arena.allocator();
// Parse once
var parser = koru_parser.Parser.init(allocator, BENCH_FLOW, "bench", &[_][]const u8{}, null) catch {
std.debug.print(" ERROR: Parser init failed\n", .{});
return;
};
defer parser.deinit();
const parse_result = parser.parse() catch {
std.debug.print(" ERROR: Parse failed\n", .{});
return;
};
// Find the flow
var flow_ptr: ?*const @import("ast").Flow = null;
for (parse_result.source_file.items) |*item| {
if (item.* == .flow) {
flow_ptr = &item.flow;
break;
}
}
if (flow_ptr == null) {
std.debug.print(" ERROR: No flow found\n", .{});
return;
}
// Warm up (run a few iterations) using reusable env/bindings
var env = koru_std.interpreter.Environment.init(allocator);
defer env.deinit();
var expr_bindings = koru_std.interpreter.ExprBindings.init(allocator);
defer expr_bindings.deinit();
for (0..3) |_| {
env.clear();
expr_bindings.clear();
var ctx = koru_std.interpreter.InterpreterContext{
.env = &env,
.expr_bindings = &expr_bindings,
.allocator = allocator,
.dispatcher = &dispatch_bench,
};
_ = koru_std.interpreter.executeFlow(flow_ptr.?, &ctx) catch continue;
}
// Time it
const start = std.time.nanoTimestamp();
for (0..ITERATIONS) |_| {
env.clear();
expr_bindings.clear();
var ctx = koru_std.interpreter.InterpreterContext{
.env = &env,
.expr_bindings = &expr_bindings,
.allocator = allocator,
.dispatcher = &dispatch_bench,
};
_ = koru_std.interpreter.executeFlow(flow_ptr.?, &ctx) catch continue;
}
const end = std.time.nanoTimestamp();
const total_ns = end - start;
const per_iter_ns = @divTrunc(total_ns, ITERATIONS);
const per_iter_us = @divTrunc(per_iter_ns, 1000);
std.debug.print(" Total: {d} ms\n", .{@divTrunc(total_ns, 1_000_000)});
std.debug.print(" Per execution: {d} us ({d} ns)\n", .{per_iter_us, per_iter_ns});
std.debug.print(" (Each execution = 100 loop iterations + 100 add dispatches)\n", .{});
}
// ========================================================================
// BENCHMARK 3: Parse time only
// ========================================================================
std.debug.print("[3] PARSE ONLY: ~for(0..100) flow\n", .{});
std.debug.print(" Iterations: {d}\n", .{ITERATIONS});
{
// Time parsing only
const start = std.time.nanoTimestamp();
for (0..ITERATIONS) |_| {
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
defer arena.deinit();
var parser = koru_parser.Parser.init(arena.allocator(), BENCH_FLOW, "bench", &[_][]const u8{}, null) catch continue;
defer parser.deinit();
_ = parser.parse() catch continue;
}
const end = std.time.nanoTimestamp();
const total_ns = end - start;
const per_iter_ns = @divTrunc(total_ns, ITERATIONS);
const per_iter_us = @divTrunc(per_iter_ns, 1000);
std.debug.print(" Total: {d} ms\n", .{@divTrunc(total_ns, 1_000_000)});
std.debug.print(" Per parse: {d} us ({d} ns)\n", .{per_iter_us, per_iter_ns});
}
std.debug.print("\n", .{});
std.debug.print("============================================================\n", .{});
std.debug.print("COMPARE WITH: python3 benchmark.py\n", .{});
std.debug.print("============================================================\n", .{});
}
Test Configuration
MUST_RUN