Render numbers the way Microsoft BASIC does - #124
Merged
Conversation
PRINT emitted bare digits, so numbers collided with adjacent literals: `PRINT "THERE ARE NOW";N;"MATCHES REMAINING."` produced `THERE ARE NOW20MATCHES REMAINING.` where every 8K BASIC produces `THERE ARE NOW 20 MATCHES REMAINING.`. Microsoft renders a number as sign-or-space, digits, then a trailing space. STR$ already implemented the leading half of that rule, so PRINT and STR$ disagreed. Numeric rendering also leaked Go's float64 conventions: a leading zero before the decimal point, a lowercase exponent marker, no exponent form for large magnitudes, and up to sixteen significant digits. Add basicNumberString and formatNumber, shared by PRINT and STR$. Values now carry nine significant digits, matching Microsoft's five-byte float; fixed-point form drops the leading zero and trailing zeros; magnitudes outside [0.01, 1e9) use exponent form such as 1E-03 or 1.23456789E+09. Rounding to nine digits subsumes the ad-hoc binary-residue heuristic, which is removed. Expected transcripts were captured from this interpreter, so they encoded the old spacing and are updated throughout. Each replacement had to match its original with spaces stripped, proving only spacing changed; the precision-sensitive ones were verified individually against the nine-digit rule. The Count assertions on RIGHT and WRONG are re-anchored to their new column, since their counts depend on it. Closes #119 Closes #120 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #119. Closes #120.
Behavior
Microsoft renders a number as sign-or-space, digits, trailing space, and
go-basicemitted bare digits. It also leaked Go's float64 conventions into numeric output.Before / after
PRINT 1;2;31231 2 3PRINT -7-7-7PRINT .50.5.5PRINT 1/30.3333333333333333.333333333PRINT 1E10100000000001E+10PRINT 1E-101e-101E-10Boundaries, all covered by tests:
.0099999→9.9999E-03,.01→.01,999999999→999999999,1E9→1E+09.Design notes
basicNumberStringis shared byPRINTandSTR$.PRINTappends the trailing space;STR$does not. PreviouslySTR$implemented the leading half of the rule andPRINTimplemented none of it, so the two disagreed with each other — that inconsistency is what identified this as an oversight rather than a deliberate choice.1e-14binary-residue heuristic, which is deleted rather than kept alongside it.[0.01, 1e9)switches to exponent form.Test expectations
The expected transcripts were captured from this interpreter, so they encoded the defect — for example
test/cli_test.goassertedA1POINT BAGELS BUFF!!where the original printsA 1 POINT BAGELS BUFF!!, and one literal (245.354056071945743.5) was a mid-number fragment of two columns run together. 148 expectations are updated acrosspkg/interpreter,cmd/go-basic, andtest.These were rewritten with tooling under two constraints, not by accepting output blindly:
113.5528725660044→113.552873.Reviewer note: two deliberate assertion changes
strings.Count(transcript, " RIGHT")and the matchingWRONGare re-anchored from 11 to 10 leading spaces. Their counts depend on the column, so this needed to stay column-anchored rather than become a bare word match.Containsassertions lost incidental leading whitespace (e.g." ***** END OF FIRST HALF *****…"). Their content assertions are unchanged and none of them feed aCount, so no assertion changed meaning, but they are marginally less strict than before.Derivation
These expectations follow the documented Microsoft rules; they were not captured from a reference implementation.
TestEvaluatorFormatsNumbersLikeMicrosoftpins the rules independently of any transcript, and every boundary above is asserted there. If the rules are ever checked against a real 6502 BASIC, that test is the single place to reconcile.Commands run
Full CI gate, green on the committed state:
The gate caught a stale expectation in
cmd/go-basicthat focused runs over./pkg/interpreterand./testhad missed.Not fixed here
#122 —
TAB/SPCallocate unbounded padding. Untouched by this change.🤖 Generated with Claude Code