Skip to content

Fix character print/read round-trip for glyphs and control names#75

Merged
pmatos merged 2 commits into
mainfrom
issue-73
Jul 1, 2026
Merged

Fix character print/read round-trip for glyphs and control names#75
pmatos merged 2 commits into
mainfrom
issue-73

Conversation

@pmatos

@pmatos pmatos commented Jul 1, 2026

Copy link
Copy Markdown
Owner

Summary

Fixes the two character print → re-read round-trip gaps tracked in #73, where a printed character did not read back as the same character.

  • Multi-byte glyph literals (Bug 1). maybeLexSchemeChar checked the followup delimiter at byte offset 1, which lands inside a multi-byte UTF-8 glyph. Printed forms like #\λ therefore failed to lex back as a character — and, worse, drove parseQuote/parseValue into unbounded recursion (stack overflow) rather than the symbol fallback the issue predicted. The followup offset now advances by the glyph's UTF-8 byte length.
  • Control-char print names (Bug 2). charReprFromCodePoint emits Racket's print names (nul, vtab, page, rubout), but the reader's isCharacterName table only knew null/delete and lacked vtab/page, so #\nul/#\vtab/#\page/#\rubout read back as symbols. The table now accepts these print names, with null ordered before nul so #\null is not truncated.

Test plan

  • ctest --preset debug — 13/13 passing (includes the lit integration suite)
  • nora-lit test/integration -v — 54/54 passing, including 6 new round-trip tests
  • clang-format --dry-run --Werror src/Lex.cpp — clean
  • Manual repro confirms #\λ, #\nul, #\vtab, #\page, #\rubout now round-trip; #\null still lexes
  • New regression tests added (test/integration/char-*-read.rkt)

Fixes #73

maybeLexSchemeChar checked the followup delimiter at byte offset 1, which
falls inside a multi-byte UTF-8 glyph, so printed forms like #\λ failed to
lex back as a character (and drove parseQuote/parseValue into unbounded
recursion). Advance the followup offset by the glyph's UTF-8 byte length.
Also extend the reader's character-name table with the print names
nul/vtab/page/rubout so decoded control characters round-trip.
@codecov

codecov Bot commented Jul 1, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 73.71%. Comparing base (1ca9b29) to head (02d3603).

Additional details and impacted files
@@            Coverage Diff             @@
##             main      #75      +/-   ##
==========================================
+ Coverage   73.19%   73.71%   +0.52%     
==========================================
  Files          24       24              
  Lines        2108     2108              
  Branches      290      290              
==========================================
+ Hits         1543     1554      +11     
+ Misses        565      554      -11     
Flag Coverage Δ
integration 73.71% <100.00%> (+0.52%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@claude

claude Bot commented Jul 1, 2026

Copy link
Copy Markdown

Code review

No issues found. Checked for bugs and CLAUDE.md compliance.

The existing glyph test puts a delimiter right after #\λ, so the
whitespace branch of maybeLexSchemeChar's followup check was never
exercised. A glyph char in a list ('(#\λ #\a)) covers it.
@pmatos pmatos merged commit 92e1613 into main Jul 1, 2026
20 checks passed
@pmatos pmatos deleted the issue-73 branch July 1, 2026 20:24
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.

Character print/read round-trip: multi-byte glyph literals and Racket control-char names

1 participant