Skip to content

feat: enable println via trace#54

Open
mooori wants to merge 15 commits intonextfrom
mooori/print-via-trace
Open

feat: enable println via trace#54
mooori wants to merge 15 commits intonextfrom
mooori/print-via-trace

Conversation

@mooori
Copy link
Copy Markdown
Contributor

@mooori mooori commented Apr 13, 2026

  • Adds support for println-style output via a new TRACE_PRINT_LN trace event, with decoding of [address, length] from the VM stack and reading the corresponding UTF-8 bytes from memory.
  • Refactors trace handling so callbacks receive full ProcessorState instead of just the cycle, which lets the host capture trace events and read string-bytes from memory.
  • Persists printed output through the executor and ExecutionTrace, exposing it as printed_lines() keyed by cycle.
  • Extracts reusable memory-byte helpers and updates existing memory reads to use them.

Companion PR in the compiler: 1077

Comment thread Cargo.toml
@mooori
Copy link
Copy Markdown
Contributor Author

mooori commented Apr 15, 2026

This does not yet handle displaying printed lines. So far it only makes them available programmatically (example).

Marking it as ready for review because I would like to:

  • Get the internals (this PR) done first.
  • Get aligned on how to present printed lines in the UI before working on it. Especially since I'm not yet familiar with the internals of the different UI modes.

@mooori mooori marked this pull request as ready for review April 15, 2026 12:59
@djolertrk
Copy link
Copy Markdown
Collaborator

djolertrk commented Apr 21, 2026

Thanks for this! @mooori

This does not yet handle displaying printed lines. So far it only makes them available programmatically (example).

Marking it as ready for review because I would like to:

  • Get the internals (this PR) done first.

  • Get aligned on how to present printed lines in the UI before working on it. Especially since I'm not yet familiar with the internals of the different UI modes.

For this, as discussed we should be using logging / :debug.

In general, the panic! would cause the Terminal UI to crash, right?

Also, please rebase on to the latest next -- there will be more of const U32_MASK.
Also, we may want to wire this up into DAP mode as well.

@mooori
Copy link
Copy Markdown
Contributor Author

mooori commented Apr 21, 2026

In general, the panic! would cause the Terminal UI to crash, right?

Probably...to avoid it I've changed println handling to log a warning and then continue instead of panic.

Also, please rebase on to the latest next -- there will be more of const U32_MASK.

The PR is based on latest next, maybe the changes you mean are in main? See this comment above

Also, we may want to wire this up into DAP mode as well.

Added a comment regarding DAP and REPL in #55

@mooori mooori force-pushed the mooori/print-via-trace branch from 7c99d55 to 3389c9e Compare April 22, 2026 17:38
Copy link
Copy Markdown
Collaborator

@bitwalker bitwalker left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work! I have a few changes I'd like to make before we merge this, some of which we talked about on Monday, but overall LGTM! 👍

Comment thread crates/engine/src/exec/executor.rs
Comment thread crates/engine/src/exec/executor.rs Outdated
host.register_assert_failed_tracer(move |clk, event| {
assertion_events.borrow_mut().insert(clk, event);
});
let printed_lines: Rc<RefCell<BTreeMap<RowIndex, String>>> = Rc::new(Default::default());
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than capturing printed strings this way, I would simply log them in the trace handler, like so:

log::log!(target: "stdout", Level::Info, "{content}");

We could potentially also emit log metadata that attaches the current procedure name (if known) to each logged print statement, but that's probably not needed for the time being.

This will get picked up by the TUI debug log window, and also get output when trace logs are enabled in our test suite.

For testing this functionality, you can install the DebugLogger as the log handler, run a program that emits some trace lines, and then do:

let entries = DebugLogger::get().take_captured();
let prints = entries.iter().filter_map(|entry| if entry.target == "println" { Some(&entry.message) } else { None }).collect::<Vec<_>>();

Then assert whatever you want about the printed messages.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've been getting more familiar with the TUI and I noticed that DebugPane shows everything that was logged. Probably that's on purpose and I can see how that's helpful when working on the debugger itself.

For someone using the debugger to inspect their program, I would imagine that they only want to see what they passed into println. Seeing internal state updates and other internal logs might be confusing for them.

So I've been wondering: Should we add another pane that only shows messages logged via println? If yes, the println messages could be obtained by:

  • filtering the content of DebugLogger
  • storing printed_lines; as currently done or in some other way

Another way of filtering would be setting a log level, e.g. running the debugger with RUST_LOG=info. Though that's another step to take for the end user.

Seems like even with RUST_LOG=info the DebugPane contains messages with lower prio such as debug. I have to double check and will open an issue if that's the case.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We use MIDENC_TRACE, not RUST_LOG - but in any case, I do think it could be worthwhile to have another debug-like window that shows just log entries whose target is stdout.

Or perhaps, it would be better still to have the default display of the debug window already be filtering for the stdout target, and provide keys to toggle the filtering - that way we can largely re-use the existing functionality, but make it more useful. I'd kinda prefer to avoid adding a bunch of panes and windows if existing ones can be extended to provide the same functionality in an ergonomic way.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done and opened #60

Comment thread crates/engine/src/exec/executor.rs Outdated
Comment thread crates/engine/src/exec/executor.rs Outdated
Comment thread crates/engine/src/exec/trace_event.rs Outdated
@mooori
Copy link
Copy Markdown
Contributor Author

mooori commented Apr 23, 2026

I've addressed the review comments and opened #60 for debug window filtering.

The printed_lines field is removed and the println content is now captured only by log. For the TUI mode that is handled by DebugLogger. I've also opened issues to handle them in the DAP #61 and REPL #62.

Tests have been ported to work with DebugLogger. DebugLogger is gated behind the tui feature and I suppose this shouldn't change. Because when using the debugger as a library, DebugLogger might conflict with the user's instance of env_logger. As a result, println related tests are now also behind the tui feature.

The tests in the compiler will need to be reworked too, as now they no longer have direct access to printed_lines via the ExecutionTrace.

Previously DebugLoggers buffer was limited to 100 log entries. As debug logging is quite verbose, this was not sufficient to capture println messages in tests. I've bumped it to 1000, assuming that's still manageable for the average device running the debug logger.

@mooori mooori requested a review from bitwalker April 23, 2026 17:21
@mooori
Copy link
Copy Markdown
Contributor Author

mooori commented Apr 23, 2026

Just saw that there's a minor conflict with next. I'll wait with rebasing and the related force-push, to not disturb the ongoing review.

Copy link
Copy Markdown
Collaborator

@bitwalker bitwalker left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just about there! I think we can simplify things a bit by using integration tests instead of unit tests, so as to avoid the complexities around concurrent testing with a global resource like the logger.

Comment thread src/logger.rs Outdated
Comment thread src/logger.rs Outdated
Comment thread src/trace_println_tests.rs Outdated
@mooori
Copy link
Copy Markdown
Contributor Author

mooori commented Apr 28, 2026

I've addressed the review comments. Making the println tests integration tests went smoothly overall. Things to note:

  • Had to make some test helpers public to use them in integration tests
  • Added [[test]] entries to Cargo.toml to feature gate println tests behind tui, which is required to use DebugLogger

@mooori mooori requested a review from bitwalker April 28, 2026 10:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants