Skip to content

Fix HEREDOC parsing inside BEGIN blocks (#366)#367

Merged
fglock merged 3 commits intomasterfrom
fix/heredoc-begin-block
Mar 24, 2026
Merged

Fix HEREDOC parsing inside BEGIN blocks (#366)#367
fglock merged 3 commits intomasterfrom
fix/heredoc-begin-block

Conversation

@fglock
Copy link
Owner

@fglock fglock commented Mar 24, 2026

Summary

Fixes #366 - HEREDOC parsing now works correctly inside BEGIN blocks.

When a HEREDOC is declared inside a BEGIN block (e.g., BEGIN { eval <<'END' }), the heredoc content appears on subsequent lines after the block closes. However, BEGIN blocks execute immediately during parsing, before the newline that triggers heredoc content processing.

Changes

  • Parser.java: Added heredocSkipToIndex field to track where to skip after pre-processed heredocs
  • SpecialBlockParser.java: Before executing BEGIN blocks, process any pending heredocs by:
    1. Finding the next NEWLINE token
    2. Temporarily advancing to process heredocs
    3. Storing the post-heredoc position
    4. Restoring tokenIndex for normal parsing
  • Whitespace.java: When encountering a NEWLINE with heredocSkipToIndex set, skip past already-processed heredoc content

Test Plan

  • Minimal reproducer now works:
    BEGIN {if (0){1}else {eval <<'END'}}print "after\n";
    hello
    END
  • CPAN::Meta::YAML pattern works (simplified test case)
  • Multiple heredocs in BEGIN block work
  • All unit tests pass
  • Output matches system Perl for all test cases

Impact

This enables cpanm and other tools that load CPAN::Meta::YAML, which uses this pattern for optional dependency loading.

Generated with Devin

@fglock fglock force-pushed the fix/heredoc-begin-block branch 2 times, most recently from f9439a4 to c8049e1 Compare March 24, 2026 13:22
When a HEREDOC is declared inside a BEGIN block (e.g., `BEGIN { eval <<'END' }`),
the heredoc content appears on subsequent lines after the block closes. However,
BEGIN blocks execute immediately during parsing, before the newline that triggers
heredoc content processing.

The fix processes any pending heredocs before executing BEGIN blocks:
1. After parsing the closing `}` of a BEGIN block, check for pending heredocs
2. If found, temporarily advance to the next NEWLINE and process heredocs
3. Store the post-heredoc position for later skip
4. Restore tokenIndex to continue normal parsing
5. When later encountering the NEWLINE in normal parsing, skip past the
   already-processed heredoc content

This enables CPAN::Meta::YAML and other modules that use this pattern.

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@fglock fglock force-pushed the fix/heredoc-begin-block branch from c8049e1 to 1bee908 Compare March 24, 2026 13:32
fglock and others added 2 commits March 24, 2026 14:35
The -t file test operator now correctly checks if standard streams
are connected to a terminal using POSIX isatty(). Previously, -t STDIN
always returned undef/false, causing programs like cpanm to incorrectly
try to read module names from STDIN when run interactively.

This fixes cpanm hanging in interactive terminals when STDIN is
actually a TTY but -t STDIN was returning false.

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
The CycloneDX plugin outputs warnings about unknown JSON schema keywords
(meta:enum, deprecated) which are harmless but noisy. Redirect the task
stdout/stderr to INFO level to suppress these warnings during normal builds.

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@fglock fglock force-pushed the fix/heredoc-begin-block branch from 188e4b7 to a7d555a Compare March 24, 2026 13:42
@fglock fglock merged commit 8aab241 into master Mar 24, 2026
2 checks passed
@fglock fglock deleted the fix/heredoc-begin-block branch March 24, 2026 13:59
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.

HEREDOC parsing fails inside BEGIN blocks

1 participant