diff --git a/eo-runtime/src/main/java/org/eolang/AtWithRho.java b/eo-runtime/src/main/java/org/eolang/AtWithRho.java index bb25fffa51..30f514ace3 100644 --- a/eo-runtime/src/main/java/org/eolang/AtWithRho.java +++ b/eo-runtime/src/main/java/org/eolang/AtWithRho.java @@ -71,4 +71,12 @@ public Phi get() { public void put(final Phi phi) { this.origin.put(phi); } + + /** + * Returns the original attribute. + * @return The original attribute + */ + public Attr getOrigin() { + return this.origin; + } } diff --git a/eo-runtime/src/main/java/org/eolang/PhDefault.java b/eo-runtime/src/main/java/org/eolang/PhDefault.java index 4de4f93877..d05ad51c8d 100644 --- a/eo-runtime/src/main/java/org/eolang/PhDefault.java +++ b/eo-runtime/src/main/java/org/eolang/PhDefault.java @@ -140,7 +140,17 @@ public boolean hasRho() { @Override public void put(final int pos, final Phi object) { - this.put(this.attr(pos), object); + final String name = this.attr(pos); + final AtWithRho attribute = (AtWithRho) this.attrs.get(name); + if (!(attribute.getOrigin() instanceof AtVoid)) { + throw new ExReadOnly( + String.format( + "There are no void attributes left, can't set the %s one", + PhDefault.ordinal(pos) + ) + ); + } + this.put(name, object); } @Override @@ -336,4 +346,34 @@ private static void debug(final String msg) { private static String padding() { return String.join("", Collections.nCopies(PhDefault.NESTING.get(), "ยท")); } + + /** + * Returns the ordinal representation of a number (e.g., "1st", "2nd", "3rd", "4th"). + * @param number The number to format + * @return The number with its ordinal suffix + */ + private static String ordinal(final int number) { + final int lasts = number % 100; + final int last = number % 10; + final String suffix; + if (lasts >= 11 && lasts <= 13) { + suffix = "th"; + } else { + switch (last) { + case 1: + suffix = "st"; + break; + case 2: + suffix = "nd"; + break; + case 3: + suffix = "rd"; + break; + default: + suffix = "th"; + break; + } + } + return number + suffix; + } } diff --git a/eo-runtime/src/test/java/org/eolang/PhDefaultTest.java b/eo-runtime/src/test/java/org/eolang/PhDefaultTest.java index 1addd5b097..8056f89ca2 100644 --- a/eo-runtime/src/test/java/org/eolang/PhDefaultTest.java +++ b/eo-runtime/src/test/java/org/eolang/PhDefaultTest.java @@ -23,6 +23,7 @@ */ package org.eolang; +import EOorg.EOeolang.EOnumber; import com.yegor256.Together; import java.security.SecureRandom; import org.cactoos.set.SetOf; @@ -488,6 +489,19 @@ void doesNotCalculateRandomTwice() { ); } + @Test + void failsCorrectlyWhenTooManyAttributesPut() { + MatcherAssert.assertThat( + "the message explains what's going on", + Assertions.assertThrows( + ExAbstract.class, + () -> new EOnumber().put(1, new Data.ToPhi(1)), + "fails when trying to set attribute with too big position" + ).getMessage(), + Matchers.equalTo("There are no void attributes left, can't set the 1st one") + ); + } + /** * Rnd. * @since 0.1.0