Skip to content

Add trace statement support#14

Open
wtalioy wants to merge 1 commit into
tea-compiler:mainfrom
wtalioy:trace-only
Open

Add trace statement support#14
wtalioy wants to merge 1 commit into
tea-compiler:mainfrom
wtalioy:trace-only

Conversation

@wtalioy

@wtalioy wtalioy commented Jun 28, 2026

Copy link
Copy Markdown

What

Adds source-level trace support to TeaLang.

New syntax:

trace foo(1, 2);

traces a function call used as a statement.

let x:i32 = trace foo(1);

traces a function call used as an expression.

A traced call prints a structured execution trace for the traced call tree, including:

  • function calls and argument values
  • scalar local definitions
  • scalar assignment changes
  • if and while condition results
  • loop iteration counts
  • nested traced calls
  • return values

Example input from tests/trace_basic/trace_basic.tea:

use std;

fn lower_bound(x:i32) -> i32 {
    let l:i32 = 0;
    let r:i32 = 5;
    while l < r {
        let m:i32 = (l + r) / 2;
        if m < x {
            l = m + 1;
        } else {
            r = m;
        }
    }
    return l;
}

fn main() -> i32 {
    trace lower_bound(3);
    return 0;
}

Actual end-to-end output:

trace lower_bound(3)
call lower_bound(x = 3)
  let l = 0
  let r = 5
  while l < r -> true
  loop #1
    let m = 2
    if m < x -> true
      l: 0 -> 3
  while l < r -> true
  loop #2
    let m = 4
    if m < x -> false
    else
      r: 5 -> 4
  while l < r -> true
  loop #3
    let m = 3
    if m < x -> false
    else
      r: 4 -> 3
  while l < r -> false
  return 3
end trace
0

Instrumentation is driven by explicit trace roots in the source program. Only user-defined functions reachable from trace call sites are instrumented; ordinary non-traced calls keep their existing behavior.

How

Parser/AST: adds trace_stmt and trace_call grammar rules, plus TraceStmt and ExprUnitInner::TraceCall AST variants. This supports trace in both statement position and expression position.

Trace planning: adds an IR trace planner that walks the AST, finds explicit trace roots, builds the reachable user-function call set, and enables instrumentation only for those functions.

IR generation: emits trace runtime calls around traced calls and inside instrumented functions. It records function entry arguments, scalar let bindings, scalar assignment changes, branch conditions, loop iterations, and returns.

Runtime helpers: adds C helper functions in the test standard library for trace session state, indentation, event limiting, text output, integer output, and boolean output.

Type handling: teaches normal type inference and the experimental return-inference path to treat traced calls like ordinary function calls for type checking.

Testing

Adds end-to-end trace tests:

  • trace_basic: traces a binary-search-style function with locals, while, if/else, assignments, and return output.
  • trace_recursive: verifies recursive traced calls, nested indentation, and return events.
  • trace_nested_tree: verifies nested non-recursive calls and local definition output.
  • trace_array: verifies array element assignment change output such as a[1]: 1 -> 4.
  • trace_value: verifies trace in expression position and continued use of the traced return value.

Validated with:

cargo check
cargo test trace_ -- --nocapture
cargo test
cargo check --features return-type-inference

All pass.

Copilot AI review requested due to automatic review settings June 28, 2026 16:31

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Adds a new trace construct to TeaLang (usable both as a statement and as an expression) and threads it through parsing, AST, type checking, IR planning, IR generation, and a small C runtime to emit structured execution traces for explicitly traced call trees.

Changes:

  • Extends the TeaLang grammar/parser/AST to support trace <fn_call> in both statement and expression positions.
  • Adds a trace planner + IR instrumentation to emit trace events for explicitly traced call trees (calls, scalar lets, scalar assignment diffs, if/while condition results, loop counts, returns).
  • Adds end-to-end golden tests for trace output and a small trace runtime in the test stdlib (tests/std/std.c).

Reviewed changes

Copilot reviewed 32 out of 32 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
tests/trace_value/trace_value.tea Adds an e2e test for trace in expression position.
tests/trace_value/trace_value.out Golden output for trace_value.
tests/trace_value/std.teah Minimal std header for the trace_value test.
tests/trace_recursive/trace_recursive.tea Adds an e2e test for recursive traced calls.
tests/trace_recursive/trace_recursive.out Golden output for trace_recursive.
tests/trace_recursive/std.teah Std header used by trace_recursive.
tests/trace_nested_tree/trace_nested_tree.tea Adds an e2e test for nested (non-recursive) call trees.
tests/trace_nested_tree/trace_nested_tree.out Golden output for trace_nested_tree.
tests/trace_nested_tree/std.teah Std header used by trace_nested_tree.
tests/trace_basic/trace_basic.tea Adds an e2e test covering while/if/assignments/return tracing.
tests/trace_basic/trace_basic.out Golden output for trace_basic.
tests/trace_basic/std.teah Std header used by trace_basic.
tests/trace_array/trace_array.tea Adds an e2e test for array element assignment change tracing.
tests/trace_array/trace_array.out Golden output for trace_array.
tests/trace_array/std.teah Std header used by trace_array.
tests/tests.rs Registers the new trace tests in the full e2e suite.
tests/std/std.c Adds trace session state + printing helpers used by instrumented code.
src/tealang.pest Adds kw_trace, trace_stmt, and trace_call grammar rules.
src/parser/stmt.rs Parses trace_stmt into a new AST statement variant.
src/parser/expr.rs Parses trace_call in expression position into a new AST expression-unit variant.
src/ir/gen/type_infer.rs Treats traced calls like normal calls during type inference.
src/ir/gen/trace.rs Introduces trace planning and trace IR emission helpers (new module).
src/ir/gen/module_gen.rs Plans traced function set, registers runtime stubs, and enables per-function instrumentation.
src/ir/gen/function_gen.rs Emits trace events for calls/lets/assignments/branches/loops/returns and lowers trace statements/expressions.
src/ir/gen.rs Wires the new trace generator module into IR generation.
src/ir/function.rs Adds trace_enabled flag to FunctionGenerator to gate instrumentation.
src/experimental/return_infer.rs Treats traced calls like normal calls in return-type inference mode.
src/ast/tree.rs Adds AST tree display support for TraceStmt and TraceCall.
src/ast/stmt.rs Adds TraceStmt and CodeBlockStmtInner::Trace.
src/ast/expr.rs Adds ExprUnitInner::TraceCall.
src/ast/display.rs Adds display formatting for TraceCall.
src/ast.rs Re-exports TraceStmt.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/ir/gen/trace.rs
Comment on lines +344 to +350
fn emit_trace_value(&mut self, value: Operand) {
match value.dtype() {
Dtype::I1 => self.emit_trace_runtime("__teac_trace_putbool", vec![value]),
Dtype::I32 => self.emit_trace_runtime("__teac_trace_putint", vec![value]),
dtype => unreachable!("trace value has unsupported dtype {dtype}"),
}
}
Comment thread tests/std/std.c
Comment on lines +45 to +55
void __teac_trace_begin(void) {
teac_trace_active = 1;
teac_trace_events = 0;
teac_trace_stopped = 0;
teac_trace_depth = 0;
}

void __teac_trace_finish(void) {
teac_trace_active = 0;
teac_trace_depth = 0;
}
Comment thread tests/tests.rs
Comment on lines +924 to +928
trace_array,
trace_basic,
trace_nested_tree,
trace_recursive,
trace_value,
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.

2 participants