Skip to content

Implement executable format argument expressions #1234

Closed

Description

@fglock

Parent: #1116
Follow-up to: #1229 and draft PR #1233

Problem

After the active-format/filehandle work, perl5_t/t/op/write.t reaches TAP 581/636. The next execution cluster requires format argument lines to run normal Perl expressions when write executes.

For example, these must supply the value for the preceding picture field at write time:

format HASH =
@<<<
${{qw[ Sun 0 Mon 1 Tue 2 Wed 3 Thu 4 Fri 5 Sat 6 ]}}{"Wed"}
.
write HASH;

Current implementation has two connected gaps:

  1. RuntimeFormat.evaluateExpression() only recognizes a small subset of global scalar access. Other AST types produce <unsupported_expr>.
  2. JVM EmitFormat.emitNodeList() serializes every non-StringNode expression as a placeholder StringNode; even a richer runtime evaluator would no longer have executable syntax. The interpreter retains parsed nodes, but still calls the same limited evaluator.

This also means expression evaluation does not yet correctly support lexical capture, package lookup, blocks, operators, method calls, tied or overloaded values, evaluation order, or ordinary Perl diagnostics.

Desired design

Keep each parsed argument expression executable in both backends, and attach its executable representation to the RuntimeFormat object. At write time, evaluate the expressions left-to-right in scalar context against the declaration's lexical/dynamic environment, then pass their results to the corresponding picture fields.

The implementation should use shared runtime/compiler machinery where possible rather than growing a second ad-hoc AST interpreter in RuntimeFormat.

Key constraints:

  • Do not stringify or serialize away nontrivial AST nodes during JVM format emission.
  • Preserve lexical variables captured by a format declared inside a sub or block.
  • Resolve package globals in the correct package, rather than hard-coding main.
  • Evaluate each argument exactly once and preserve side effects, lvalue semantics, tie dispatch, and overload behavior.
  • Propagate Perl-level errors and warnings rather than rendering placeholders or silently substituting values.
  • Keep JVM and bytecode-interpreter behavior identical.

^ fields, ^* consumption, and ~~ continuation rely on correct argument evaluation. Their formatting/continuation rules may warrant separately staged sub-work, but this issue must establish the executable-expression pipeline they depend on.

Regression coverage

Add focused project-owned tests (do not modify imported core tests), validated on system Perl first, covering at least:

  • global and lexical variables in format argument lines;
  • nested expressions such as anonymous hashes and blocks;
  • left-to-right evaluation and exactly-once side effects;
  • tied and overloaded argument values;
  • runtime errors/warnings from an argument expression;
  • a ^ field and a ~~ continuation case once expression execution is available.

Require the focused tests to pass on the JVM backend and --interpreter, then run make. Use perl5_t/t/op/write.t as integration evidence: the HASH, HASH2, BLOCK, and format-argument pragmata cases immediately after TAP 581 are useful initial targets.

Non-goals

Activity

  1. fglock commented on Oct 26, 2026

    @fglock
    OwnerAuthor

    Resolved by PR #1883, merged as 9ce6897. Format argument expressions now execute at write time on both backends, and Perl core op/write.t passes 636/636 assertions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:parserParsing compilation AST and eval behaviorarea:runtimeCore Perl runtime semanticsenhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions