Skip to content

Enable canonical .eo format check in the eo-runtime build#5579

Merged
yegor256 merged 54 commits into
masterfrom
5577
Jul 21, 2026
Merged

Enable canonical .eo format check in the eo-runtime build#5579
yegor256 merged 54 commits into
masterfrom
5577

Conversation

@yegor256

Copy link
Copy Markdown
Member

This wires the eo-maven-plugin format goal into eo-runtime's compile execution and reformats all 133 .eo sources to the canonical layout the printer produces. With the goal in check mode (autoFix off), any source that drifts from canonical form now fails the build.

The point is to make formatting a hard gate rather than a convention. This is the eo-runtime slice of #5577, which proposes the same check for every module that carries .eo sources.

Verified locally: a clean build reports "All 139 EO source(s) are formatted canonically", and the full test suite passes (1551 tests, 0 failures). Worth knowing for review: the printer's canonical output will shift slightly once #5567 and #5570 land (compact foo ++> name and short +alias form), so a follow-up reformat will be needed then; and the remaining modules named in #5577 still need the same wiring.

Wire the eo-maven-plugin `format` goal into the compile execution so a
non-canonical `.eo` source fails the build, and reformat all existing
sources to the canonical layout produced by the printer so the check
passes.
Copilot AI review requested due to automatic review settings July 16, 2026 14:03

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@github-actions github-actions Bot added the core label Jul 16, 2026
@github-actions

Copy link
Copy Markdown
Contributor

⚠️ Benchmark Comparison Unavailable

Unfortunately, one of the benchmarks is missing, and we couldn't generate a performance comparison report.

Please ensure that both the base and PR benchmark results are available for analysis.

yegor256 added 16 commits July 16, 2026 17:48
Add a per-symbol penalty (one point per character) and make the bracket
penalty progressive: the k-th parenthesis on a line costs k times its
weight, so stacking parentheses on one line is discouraged
superlinearly. Retune the weights: indent 3 to 5, bracket 7 to 15,
excess 1 to 3. Together these push the printer away from long
parenthesised inline forms toward flatter vertical layouts.

Reformat the eo-runtime sources to the new canonical layout and update
the PenaltyTest expectations and two print-pack goldens
(compares-bool-to-bytes and times).
The single-parenthesis case (default weight) is already covered by the
progressive-parentheses test (two parens = 3x the weight, which also
pins the default weight) and by the overridden-weight test. Removing it
keeps the class under the method-count limit and drops the duplicated
string literal below the threshold, so qulice passes.
Master's #5567 fix (PR #5582) added the compact `foo ++> name` test
shorthand to the parser and printer. Re-run the format goal so every
eo-runtime source adopts that shorthand together with the retuned
penalty weights, keeping the sources canonical under the merged printer.
# Conflicts:
#	eo-printer/src/test/resources/org/eolang/printer/print-packs/yaml/times.yaml
Re-run the format goal after merging master's printer fixes for #5583
(atom signatures keep their Q. root) and #5584 (data-receiver dispatch
prints in suffix form). Sources now round-trip to valid XMIR and adopt
the suffix dispatch, staying canonical under the merged printer.
Regenerate the canonical .eo sources now that the printer bugs
(#5581, #5583, #5584, #5589, #5591) are fixed on master. The
re-format is idempotent and the full eo-runtime suite passes
(1551 tests, 0 failures, 0 errors).
Cheaper indentation makes the layout search prefer vertical
renderings over deeply parenthesized inline ones. Update the two
round-trip golden packs (dataless, empty-string) and the two
PenaltyTest expectations that pinned the old default.
Regenerate the canonical .eo sources under the lowered indentation
penalty. The re-format is idempotent and the full eo-runtime suite
passes (1551 tests, 0 failures, 0 errors).
Re-run the format goal now that the printer withholds the hybrid
inline-phi collapse when any decoratee descendant is named (#5604),
so file.eo, tuple/reducedi.eo and while.eo re-parse cleanly. The
output is idempotent across two passes and the full eo-runtime suite
passes.
@yegor256

Copy link
Copy Markdown
Member Author

@maxonfjvipon take a look again (ignore the xcop failure for now)

@yegor256
yegor256 requested a review from maxonfjvipon July 17, 2026 07:34
Comment thread eo-runtime/src/main/eo/bytes/array.eo Outdated
slice-byte
tup.with (bts.slice index 1)
(index.plus 1).as-number
as-number. (index.plus 1)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yegor256 why?

Comment thread eo-runtime/src/main/eo/bool.eo Outdated
123
42
123
eq. (if. (5.eq 5) 123 42) 123 ++> tests-forks-on-true-condition

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yegor256 that's not quite readable

Comment thread eo-runtime/src/main/eo/bool.eo Outdated
eq. > @
x
42
^.^.^.x.eq 42 > [] > @

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yegor256 too much noisy rhos

Comment thread eo-runtime/src/main/eo/bytes.eo Outdated
[start len] > slice /bytes
? > cant-slice /{string}

[start len cant-slice] > slice /bytes

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yegor256 we loose /{string} here

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

plus.
timeb.time.times 1000
timeb.millitm
sm.os.is-windows.if

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yegor256 if. is much more readable than .if

+unlint mandatory-package

2.7182818284590452354 > e
2.718281828459045 > e

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yegor256 precision loosing

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@maxonfjvipon it was over-precise: #5613

*
if.
contains prev.hashes hash
tuple.contains prev.hashes hash

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yegor256 unnecessary tuple

Comment thread eo-runtime/src/main/eo/mktemp.eo Outdated
getenv "TMP" > tmp!
getenv "TMPDIR" > tmpdir!
getenv "USERPROFILE" > userprofile!
as-bytes. > temp

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yegor256 ! is lost

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment thread eo-runtime/src/main/eo/stderr.eo Outdated

seq > @
* (output.write text) true
sm.os.is-windows.if windows-output posix-output > output

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yegor256 unreadable

Comment thread eo-runtime/src/main/eo/string.eo Outdated

++> throws-on-taking-length-of-incomplete-n4-byte-character
(string F0-9F-98).length > @
"�".length ++> throws-on-taking-length-of-incomplete-n4-byte-character

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yegor256 ???

yegor256 added 6 commits July 17, 2026 16:56
# Conflicts:
#	eo-runtime/src/main/eo/bytes.eo
#	eo-runtime/src/main/eo/bytes/as-i16.eo
#	eo-runtime/src/main/eo/bytes/as-i32.eo
#	eo-runtime/src/main/eo/bytes/as-i64.eo
#	eo-runtime/src/main/eo/bytes/as-number.eo
#	eo-runtime/src/main/eo/directory.eo
#	eo-runtime/src/main/eo/file.eo
#	eo-runtime/src/main/eo/i16.eo
#	eo-runtime/src/main/eo/i32.eo
#	eo-runtime/src/main/eo/i64.eo
#	eo-runtime/src/main/eo/map.eo
#	eo-runtime/src/main/eo/number.eo
#	eo-runtime/src/main/eo/number/mod.eo
#	eo-runtime/src/main/eo/string.eo
#	eo-runtime/src/main/eo/string/as-number.eo
#	eo-runtime/src/main/eo/string/at.eo
#	eo-runtime/src/main/eo/string/nsplit.eo
#	eo-runtime/src/main/eo/string/printf.eo
#	eo-runtime/src/main/eo/string/regex.eo
#	eo-runtime/src/main/eo/string/repeated.eo
#	eo-runtime/src/main/eo/string/scanf.eo
#	eo-runtime/src/main/eo/switch.eo
#	eo-runtime/src/main/eo/tuple.eo
#	eo-runtime/src/main/eo/tuple/maximum.eo
#	eo-runtime/src/main/eo/tuple/minimum.eo
#	eo-runtime/src/main/eo/tuple/range-of-numbers.eo
Re-run the format goal over eo-runtime after merging the printer
round-trip fixes from master (#5620 lossy UTF-8 decode, #5622 and #5624
trailing-star hybrid). The output is now idempotent (a second format
pass reports no divergence) and provably lossless: every reformatted
source parses to the same object tree as before, modulo line numbers
and position-derived auto-names.
The penalty function now charges APPLICATION (7 points by default) for
every space on a line beyond its leading indentation, so bracket- and
space-heavy horizontal forms give way to vertical ones. All print-packs
pin the new weight and a handful of goldens are reconciled to the new
layout.
Re-run the canonical formatter over all .eo sources now that the printer
charges the APPLICATION penalty, breaking bracket- and space-heavy
horizontal lines onto vertical layouts. 75 of 139 files changed. The
reformat is idempotent, every source parses, and all XMIR trees are
identical to before, so the change is purely cosmetic.
yegor256 and others added 10 commits July 20, 2026 12:11
Pull master's #5650: suffixed() now rebuilds any reversed dispatch whose
receiver has a one-line form as "(receiver).method", not only lone-data
receivers. The merge keeps 5577's penalty weights, so this suffix-glue is
generated and wins wherever it beats the reversed vertical form.
Regenerate the seven print-pack fixtures whose pinned output shifted to
the resulting hybrid: "(x).method" with the remaining arguments kept
vertical. All 141 eo-printer tests pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Re-canonicalize the runtime .eo under master's #5650, just merged in.
A reversed dispatch whose receiver has a one-line form now prints as
"(receiver).method" wherever that beats the vertical reversed form,
collapsing many two- and three-line test attributes onto one line
(e.g. "(true.eq 42).not ++> tests-..."). Idempotent and lossless: all
97 changed files parse to the same object tree as before.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The descriptive comment blocks restate what each pack's origin,
penalties and printed fields already show. Remove them, keeping the
SPDX header and the yamllint line-length directive.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Drop the printer's default INDENT weight from 3 to 2 so vertical layout
costs less and wins more often over compact bracketed dispatch. Adjust
the two penalty assertions that read the INDENT default (five levels
15->10, two levels 6->4).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Re-canonicalize the runtime .eo now that vertical layout is cheaper.
Many compact "(receiver).method" one-liners give way to the vertical
reversed dispatch again, since the saved indentation no longer offsets
the bracket. Idempotent and lossless: all 80 changed files parse to the
same object tree as before.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The penalty-based printer charged its per-space weight flatly, once per
space on a line, so each extra argument cost the same constant increment no
matter how long the application already was. Nothing pushed the printer, or
the author, away from a sprawling application.

Now the genuine argument-applying spaces on a line pay a super-linear
surcharge: r such spaces cost r squared, rather than r, times the weight, so
longer applications grow super-linearly more expensive and the printer
favours shorter ones (for the three arguments in "foo bar 42 44" the weight
is effectively multiplied by three). Spaces that merely bind a name (">",
">>", "++>") or separate the void attributes inside a formation's "[..]"
head are not applications, so they keep their flat per-space charge and are
left untouched: "foo > [] > bar" is unchanged.

Renamed the PenaltyKey.APPLICATION weight to PenaltyKey.SPACE, since it is
charged for every space on a line, not only for argument applications, and
the print-pack weight blocks with it.

Regenerated the affected eo-printer print-pack goldens. Scoped to
eo-printer; reformatting eo-runtime sources is a separate concern and is not
included here.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KL51NxsYxxo34h6s7iVByZ
#5653: scale the per-space penalty super-linearly by application length
Re-canonicalize eo-runtime sources with the eo-printer from PR #5654,
whose per-space penalty now grows as the square of an application's
length. Sprawling multi-argument applications wrap into vertical form.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Bring in #5655, which adds a PHI(15) penalty steering the printer away
from explicit @ renderings. Combined with this branch's richer model
(progressive BRACKET, super-linear SPACE, INDENT 2): kept the progressive
bracket cost and super-linear space surcharge, added the phi charge
alongside them, and refreshed the PenaltyTest expectations and the two
worked Javadoc examples to the merged weights. Updated the
multiline-string print-pack golden, whose preferred rendering now drops
the @ suffix now that phi is charged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Re-canonicalize eo-runtime sources with the merged eo-printer, whose new
PHI penalty from #5655 charges explicit @ renderings. Blocks that bind
their phi now fold into shorter phi-free suffix forms.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
claude and others added 6 commits July 20, 2026 11:12
`Penalty.binding()` recognised `>`, `>>` and `++>` as name-binding
markers but omitted the throwing-test marker `-->`. As a result the two
spaces flanking `-->` were charged as argument applications and paid the
super-linear SPACE surcharge, so the phi-free shorthand
`mod 5 0 --> on-mod-by-zero` scored far higher than its `++>` twin and
the layout search kept the verbose `--> name / body > @` rendering with
an explicit `@`.

Add `"-->".equals(token)` to the disjunction so the marker is treated
like `++>`, restoring the collapse (this is the regression #5653
introduced for `-->` when it added the surcharge, the untreated twin of
#5567). Update the `throws-test-attribute` print-pack golden back to the
collapsed form, add a `PenaltyTest` case, and reformat the eo-runtime
`.eo` sources whose `-->` tests now render canonically in the compact
shorthand.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RjwDHuWPVtWq2kv4VrCFyD
fix(#5657): treat throwing-test marker `--&gt;` as a name binding
The print-packs are shared (via a symlink) between eo-printer's XmirTest,
which renders them under each pack's pinned weights, and MjPrintTest,
which rendered them under the printer's default weights. After the branch
lowered the default INDENT weight, 16 packs diverged and MjPrintTest
broke in CI.

Give MjPrint the same penalty parameters MjFormat already exposes and
feed each pack's pinned weights to the mojo, so both tests lay a pack out
under the weights it declares.
Resolve the bracket-penalty conflict by adopting master's depth-weighted
brackets() from PR #5660 (each parenthesis costs its nesting depth plus
one) into this branch's richer six-term penalty model, charged linearly,
and dropping the branch's per-line n(n+1)/2 count-progression. For nested
brackets the two coincide, so no runtime .eo formatting changed; the one
affected print-pack, inline-phi-overflow, now renders vertically because
the SPACE surcharge outweighs the deep one-liner.

Also clear two pre-existing jtcop violations that block the qulice job:
rename the throwing-marker test to drop the word "test", and move the
weight-override tests out of the orphan PenaltyOverridesTest into a new
PenaltyKeyTest that maps one-to-one to PenaltyKey.
@yegor256

Copy link
Copy Markdown
Member Author

@maxonfjvipon take another look

++> tests-iterating-tuple-with-while-using-internal-iterator
data.eq arr.length > @
* 1 1 1 1 > arr
* > arr

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yegor256 why no horizontal tuple here?

Comment thread eo-runtime/src/main/eo/while.eo Outdated
[iter] >>
if. > @
max.eq 0
(^.^.max.eq 0).if > @

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yegor256 still explicit rhos

--> on-empty-switch
switch * > @
switch --> on-empty-switch
*

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yegor256 why no horizontal only-phi here?

switch * --> on-empty-switch

true
(rec-case cases).@ > found

@. > found

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yegor256 still not sure about this

+unlint mandatory-package

number 7F-F8-00-00-00-00-00-00 > nan
number > nan

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yegor256 not sure what's better here

Comment thread eo-runtime/src/main/eo/mktemp.eo Outdated
tempdir.eq empty
"/tmp"
tempdir
(tmpdir.eq empty).if

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yegor256 this ).if is not intuitive

read source length

[offset length] > read /bytes
? > cant-read /{string}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yegor256 still loosing important atom info

yegor256 added 6 commits July 20, 2026 18:58
The runtime was reformatted before #5614 taught the printer to keep the
/{...} forma-list on an atom's error-branch void, so malloc's read atom
had been folded to [offset length cant-read], dropping the cant-read
/{string} type. Reformatting the master source with the current printer
restores it; the other 138 runtime sources come out byte-identical to
their committed form.
With #5664 merged from master, the printer now collapses multi-hop
^.^. parent chains to bare names when scope resolution re-derives the
hops. Re-reformatting the master sources with the updated printer strips
those redundant hops from 16 runtime files (while.eo and others). The
rewrite is lossless — every file parses to the same XMIR as master — and
idempotent.
# Conflicts:
#	eo-printer/src/main/java/org/eolang/printer/Penalty.java
#	eo-printer/src/main/java/org/eolang/printer/PenaltyKey.java
#	eo-printer/src/test/java/org/eolang/printer/PenaltyTest.java
#	eo-printer/src/test/resources/org/eolang/printer/print-packs/yaml/nested-if-inline.yaml
#	eo-printer/src/test/resources/org/eolang/printer/print-packs/yaml/seq-star-idiom.yaml
#	eo-printer/src/test/resources/org/eolang/printer/print-packs/yaml/void-local-handle.yaml
After merging master's #5666, the printer charges a penalty for
suffix `if` (`foo.if`), so the format goal now renders every `if`
in prefix form. Re-ran the goal over master's sources; output is
idempotent and parses to identical XMIR.
Merging master's #5666 added `ifs` and `identifier`, which together
with the branch's space helpers pushed Penalty to twelve methods and
tripped PMD TooManyMethods. Inline `overflow` into `points` and
`identifier` into `ifs`, both single-use, to return to ten. The
penalty math is unchanged.
@sonarqubecloud

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
9.6% Duplication on New Code (required ≤ 3%)

See analysis details on SonarQube Cloud

@yegor256
yegor256 merged commit db4273a into master Jul 21, 2026
24 of 27 checks passed
@yegor256
yegor256 deleted the 5577 branch July 21, 2026 05:27
@0crat

0crat commented Jul 21, 2026

Copy link
Copy Markdown

@maxonfjvipon Thanks for the review! You've earned +24 points for this: +12 as a basis; +16 for the 11826 hits-of-code that you reviewed; -4 to not go over the cap. Your running score is +816; don't forget to check your Zerocracy account too).

@0crat

0crat commented Jul 21, 2026

Copy link
Copy Markdown

@yegor256 Thanks for the contribution! You've earned +4 points for this: +16 as a basis; -4 for too many hits-of-code (11826 >= 100); -8 for way too many hits-of-code (11826 >= 400); -8 for the lack of code review; +8 to give you at least something. Please, keep them coming. Your running score is +2588; don't forget to check your Zerocracy account too).

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants