Skip to content

Implement ARGF.class basics - #66

Open
edgibbs wants to merge 9 commits into
camertron:mainfrom
edgibbs:edgibbs/argf-basics
Open

Implement ARGF.class basics#66
edgibbs wants to merge 9 commits into
camertron:mainfrom
edgibbs:edgibbs/argf-basics

Conversation

@edgibbs

@edgibbs edgibbs commented Aug 8, 2026

Copy link
Copy Markdown
Collaborator

TITLE: Implement ARGF.class basics


👋

Taking a run at #5. Same approach as last time, I used Claude Code with Opus 5 as a learning partner to find my way around the codebase and its patterns, but every line here I typed myself in Neovim, along with all the mistakes that entailed. This one took a lot longer than the last two, but figured it might be a challenge as an intermediate ticket. Apologies for the size, but it was a lot adding one thing and then uncovering a new small issue.

Both failures from the issue are gone:

# before
./exe/mspec-run ruby/spec/core/argf/argv_spec.rb ruby/spec/core/argf/each_byte_spec.rb
2 files, 7 examples, 0 expectations, 0 failures, 7 errors

# after
2 files, 7 examples, 9 expectations, 0 failures, 0 errors

The String#each_byte failure listed in the issue was already fixed by #56, so this only covers the ARGF half.

🔧 Implementation Notes

A few things worth calling out:

ARGF.argv has to be ARGV itself, not a copy. argv_spec.rb:10 uses should equal, and checking against MRI 3.3.6 the identity holds for the whole read cycle, even after the array has been emptied. Since it has to stay the same object, Argf holds the ARGV RValue and shifts names off it in place. That's what changed Argf.new's signature and the small exe/ruby-exe.ts diff.

Four of the commits are prerequisites the issue doesn't mention, which is why this touches six files:

  • IO#closed? and STDIN — mspec's argf helper needs both in its ensure, so no ARGF spec could get past it
  • IO#each_byte — what ARGF delegates to
  • Enumerator#size — required by shared/each_byte.rb:49-55
  • StdinIO implements the write side only; nothing here reads from STDIN and a real readable one looked like a much bigger job.

🧪 Testing

Beyond the repro above, across the whole ruby/spec/core/argf/ directory expectations passing went from 2 to 15 and errors dropped from 154 to 145. Failures went 1 to 2, but both of those are specs that used to error out in the helper and now run far enough to fail on other missing methods.

📤 Upstream

While checking Enumerator#size against MRI I noticed each_byte_spec.rb only tests non-empty strings, so an implementation returning nil for "".each_byte.size passes — which is exactly the bug I had, since 0 is falsy in JavaScript. MRI can't fail that case. each_char, each_codepoint, and each_line have no size specs at all. Planning a small ruby/spec PR for it.

edgibbs added 9 commits August 8, 2026 06:12
So it turned out ruby/spec requires identity, not just value:

  `ARGF.argv.equal?(ARGV)`
StdinIO just implements the write side, and raises IOError for puts/write
as CRuby does matching CRuby 3.3.6.

Didn't implement reading from stdin at all yet.
Opens the current file lazily, shifting its name off argv, and returns
STDIN when no files were given. Not implemented yet is advancing to the
next file at EOF.
Adds in the EOF advancing we deffered in teh ARGF#file commit earlier.

So `read_byte()` moves to the next file when the current file is
exhausted so the bytes run across all the files.
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.

1 participant