diff --git a/.codacy.yml b/.codacy.yml index da7c753a03..4600fb220c 100644 --- a/.codacy.yml +++ b/.codacy.yml @@ -2,4 +2,4 @@ # are not available for the project. For example a lot of # package name contains capital letter and such names are conventional. exclude_paths: - - "eo-runtime/src/main/java/EOorg/EOeolang/EOmemory$EOalloc.java" + - "eo-runtime/src/main/java/EOorg/EOeolang/EOcage$EOnew.java" diff --git a/eo-runtime/src/main/eo/org/eolang/cage.eo b/eo-runtime/src/main/eo/org/eolang/cage.eo index f48e9c305b..7e760072b5 100644 --- a/eo-runtime/src/main/eo/org/eolang/cage.eo +++ b/eo-runtime/src/main/eo/org/eolang/cage.eo @@ -29,4 +29,7 @@ # This object is doing exactly the same as "memory", but allows # you to store objects, not only data. In other words, it doesn't # do dataization when objects are being stored. -[enclosure] > cage /? +[] > cage + # Make new `cage` for an object. After application this `new` object starts behave + # like `it` object. + [it] > new /? diff --git a/eo-runtime/src/main/java/EOorg/EOeolang/EOcage$EOnew.java b/eo-runtime/src/main/java/EOorg/EOeolang/EOcage$EOnew.java new file mode 100644 index 0000000000..17026eab62 --- /dev/null +++ b/eo-runtime/src/main/java/EOorg/EOeolang/EOcage$EOnew.java @@ -0,0 +1,174 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2016-2024 Objectionary.com + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* + * @checkstyle PackageNameCheck (4 lines) + */ + +package EOorg.EOeolang; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicInteger; +import org.eolang.AtSimple; +import org.eolang.Atom; +import org.eolang.Attr; +import org.eolang.Data; +import org.eolang.ExFailure; +import org.eolang.PhDefault; +import org.eolang.PhTracedLocator; +import org.eolang.PhWrite; +import org.eolang.Phi; +import org.eolang.Term; +import org.eolang.XmirObject; + +/** + * Cage.alloc object. + * @since 0.36.0 + * @checkstyle TypeNameCheck (5 lines) + */ +@XmirObject(oname = "cage.new") +public final class EOcage$EOnew extends PhDefault implements Atom { + /** + * Locator calculator. + */ + private static final AtomicInteger LOCATOR = new AtomicInteger(0); + + /** + * Cage for objects. + */ + private static final ConcurrentHashMap CAGES = new ConcurrentHashMap<>(0); + + /** + * Ctor. + * @param sigma Sigma + */ + EOcage$EOnew(final Phi sigma) { + super(sigma); + this.add("it", new EOcage$EOnew.AtEncaged()); + this.add( + "encage", + new AtSimple( + new PhWrite( + this, + "it", + rho -> new Data.ToPhi(true) + ) + ) + ); + } + + @Override + public Phi lambda() throws Exception { + return this.take("it"); + } + + /** + * Attribute that stores object. + * @since 0.36.0 + */ + private static class AtEncaged implements Attr { + /** + * Locator of encaged object. + */ + private Integer locator; + + /** + * Form of the stored object. + */ + private String forma; + + /** + * Ctor. + */ + AtEncaged() { + this(null, null); + } + + /** + * Ctor for copying. + * @param locator Locator of object in memory + * @param form The form of the object + */ + AtEncaged(final Integer locator, final String form) { + this.locator = locator; + this.forma = form; + } + + @Override + public Attr copy(final Phi self) { + return new EOcage$EOnew.AtEncaged(this.locator, this.forma); + } + + @Override + public Phi get() { + if (this.locator == null || !EOcage$EOnew.CAGES.containsKey(this.locator)) { + throw new ExFailure( + "There's no object in storage, can't read" + ); + } + return new PhTracedLocator(EOcage$EOnew.CAGES.get(this.locator), this.locator); + } + + @Override + public void put(final Phi phi) { + if (this.forma == null) { + this.forma = phi.forma(); + } else if (!this.forma.equals(phi.forma())) { + throw new ExFailure( + "Can't write an object formed by %s because object formed by %s was saved before", + phi.forma(), + this.forma + ); + } + if (this.locator == null) { + synchronized (EOcage$EOnew.LOCATOR) { + this.locator = EOcage$EOnew.LOCATOR.incrementAndGet(); + } + } + EOcage$EOnew.CAGES.put(this.locator, phi); + } + + @Override + public String φTerm() { + final String txt; + if (this.locator == null || !EOcage$EOnew.CAGES.containsKey(this.locator)) { + txt = Term.EMPTY; + } else { + txt = EOcage$EOnew.CAGES.get(this.locator).φTerm(); + } + return txt; + } + + @Override + public String toString() { + final String txt; + if (this.locator == null || !EOcage$EOnew.CAGES.containsKey(this.locator)) { + txt = Term.EMPTY; + } else { + txt = EOcage$EOnew.CAGES.get(this.locator).toString(); + } + return txt; + } + } +} diff --git a/eo-runtime/src/main/java/EOorg/EOeolang/EOmemory$EOalloc.java b/eo-runtime/src/main/java/EOorg/EOeolang/EOmemory$EOalloc.java index 948b2a8524..b22527c999 100644 --- a/eo-runtime/src/main/java/EOorg/EOeolang/EOmemory$EOalloc.java +++ b/eo-runtime/src/main/java/EOorg/EOeolang/EOmemory$EOalloc.java @@ -29,15 +29,15 @@ package EOorg.EOeolang; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicInteger; import org.eolang.AtSimple; -import org.eolang.AtVoid; import org.eolang.Atom; import org.eolang.Attr; import org.eolang.Data; import org.eolang.Dataized; import org.eolang.ExFailure; import org.eolang.PhDefault; +import org.eolang.PhWrite; import org.eolang.Phi; import org.eolang.Term; import org.eolang.XmirObject; @@ -52,12 +52,12 @@ public final class EOmemory$EOalloc extends PhDefault implements Atom { /** * Locator calculator. */ - private static final AtomicLong LOCATOR = new AtomicLong(0L); + private static final AtomicInteger LOCATOR = new AtomicInteger(0); /** * Memory. */ - private static final ConcurrentHashMap MEMORY = new ConcurrentHashMap<>(0); + private static final ConcurrentHashMap MEMORY = new ConcurrentHashMap<>(0); /** * Ctor. @@ -66,7 +66,16 @@ public final class EOmemory$EOalloc extends PhDefault implements Atom { EOmemory$EOalloc(final Phi sigma) { super(sigma); this.add("data", new EOmemory$EOalloc.AtMalloc()); - this.add("write", new AtSimple(new EOmemory$EOalloc.Write(this))); + this.add( + "write", + new AtSimple( + new PhWrite( + this, + "data", + rho -> rho.take("data") + ) + ) + ); } @Override @@ -80,9 +89,9 @@ public Phi lambda() throws Exception { */ private static class AtMalloc implements Attr { /** - * Object in memory. + * Locator of object in memory. */ - private Long locator; + private Integer locator; /** * Allocated bytes length. @@ -101,7 +110,7 @@ private static class AtMalloc implements Attr { * @param locator Locator of object in memory * @param length Allocated bytes length */ - AtMalloc(final Long locator, final Integer length) { + AtMalloc(final Integer locator, final Integer length) { this.locator = locator; this.length = length; } @@ -163,26 +172,4 @@ public String toString() { return txt; } } - - /** - * Memory.alloc.write object. - * @since 0.36.0 - */ - private static class Write extends PhDefault implements Atom { - /** - * Ctor. - * @param sigma Sigma - */ - Write(final Phi sigma) { - super(sigma); - this.add("data", new AtVoid("data")); - } - - @Override - public Phi lambda() { - final Phi rho = this.take(Attr.RHO); - rho.put("data", this.take("data")); - return rho.take("data"); - } - } } diff --git a/eo-runtime/src/main/java/org/eolang/PhDefault.java b/eo-runtime/src/main/java/org/eolang/PhDefault.java index ff2077ee81..a3aac6e071 100644 --- a/eo-runtime/src/main/java/org/eolang/PhDefault.java +++ b/eo-runtime/src/main/java/org/eolang/PhDefault.java @@ -157,19 +157,11 @@ public int hashCode() { @Override public String toString() { - String result = String.format( + return String.format( "%sν%d", this.getClass().getCanonicalName(), this.vertex ); - if (this.attrs.containsKey(Attr.DELTA)) { - result = String.format( - "%s=%s", - result, - this.attrs.get(Attr.DELTA).toString() - ); - } - return result; } @Override diff --git a/eo-runtime/src/main/java/org/eolang/PhSafe.java b/eo-runtime/src/main/java/org/eolang/PhSafe.java index 5ddc70e439..4afbbb7a36 100644 --- a/eo-runtime/src/main/java/org/eolang/PhSafe.java +++ b/eo-runtime/src/main/java/org/eolang/PhSafe.java @@ -129,6 +129,12 @@ public String forma() { @Override public byte[] delta() { - return this.origin.delta(); + try { + return this.origin.delta(); + } catch (final ExFailure ex) { + throw new EOerror.ExError( + new Data.ToPhi(EOerror.message(ex)) + ); + } } } diff --git a/eo-runtime/src/main/java/org/eolang/PhTracedEnclosure.java b/eo-runtime/src/main/java/org/eolang/PhTracedLocator.java similarity index 64% rename from eo-runtime/src/main/java/org/eolang/PhTracedEnclosure.java rename to eo-runtime/src/main/java/org/eolang/PhTracedLocator.java index 70dfcf7b99..6a28798765 100644 --- a/eo-runtime/src/main/java/org/eolang/PhTracedEnclosure.java +++ b/eo-runtime/src/main/java/org/eolang/PhTracedLocator.java @@ -28,7 +28,7 @@ import java.util.function.Supplier; /** - * Class to trace if the cage got into recursion during the dataization. + * Class to trace if the "cage.new" got into recursion during the dataization. * NOT thread-safe. * @since 0.36 * @todo #2836:60min Make the class thread safe. It has private static @@ -36,7 +36,7 @@ * Needs to synchronize this field. */ @Versionized -public final class PhTracedEnclosure implements Phi { +public final class PhTracedLocator implements Phi { /** * Name of property that responsible for keeping max depth. @@ -45,21 +45,20 @@ public final class PhTracedEnclosure implements Phi { MAX_CAGE_RECURSION_DEPTH_PROPERTY_NAME = "EO_MAX_CAGE_RECURSION_DEPTH"; /** - * Cages that are currently dataizing. If one cage is datazing, and - * it needs to be dataized inside current dataizing, the cage will be here. + * Cages that are currently being dataized. If one cage is being datazed, and + * it needs to be dataized inside current dataization, the locator of current object be here. */ - private static final Map DATAIZING_CAGES = new HashMap<>(); + private static final Map DATAIZING_CAGES = new HashMap<>(); /** - * Enclosure. + * Encaged object itself. */ - private final Phi enclosure; + private final Phi object; /** - * Vertex of cage where the {@link PhTracedEnclosure#enclosure} - * was retrieved. + * Locator of encaged object. */ - private final Phi cage; + private final Integer locator; /** * Max depth of cage recursion. @@ -68,78 +67,78 @@ public final class PhTracedEnclosure implements Phi { /** * Ctor. - * @param enclosure Enclosure. - * @param cage Vertex of source cage. + * @param object Encaged object + * @param locator Locator of encaged object */ - public PhTracedEnclosure(final Phi enclosure, final Phi cage) { + public PhTracedLocator(final Phi object, final Integer locator) { this( - enclosure, - cage, + object, + locator, Integer.parseInt( - System.getProperty(PhTracedEnclosure.MAX_CAGE_RECURSION_DEPTH_PROPERTY_NAME, "100") + System.getProperty(PhTracedLocator.MAX_CAGE_RECURSION_DEPTH_PROPERTY_NAME, "100") ) ); } /** * The main constructor. - * @param enclosure Enclosure. - * @param cage Cage. - * @param depth Max depth of cage recursion. + * @param object Encaged object + * @param locator Locator of encaged object + * @param depth Max depth of cage recursion */ - public PhTracedEnclosure(final Phi enclosure, final Phi cage, final int depth) { - this.enclosure = enclosure; - this.cage = cage; + public PhTracedLocator(final Phi object, final Integer locator, final int depth) { + this.object = object; + this.locator = locator; this.depth = depth; } @Override public Phi copy() { - return new PhTracedEnclosure(this.enclosure.copy(), this.cage); + return new PhTracedLocator(this.object.copy(), this.locator); } @Override public Phi take(final String name) { - return new PhTracedEnclosure.TracingWhileGetting<>( - () -> this.enclosure.take(name) + return new PhTracedLocator.TracingWhileGetting<>( + () -> this.object.take(name) ).get(); } @Override public Phi take(final String name, final Phi rho) { - return new PhTracedEnclosure.TracingWhileGetting<>( - () -> this.enclosure.take(name, rho) + return new PhTracedLocator.TracingWhileGetting<>( + () -> this.object.take(name, rho) ).get(); } @Override - public void put(final int pos, final Phi object) { - this.enclosure.put(pos, object); + public void put(final int pos, final Phi obj) { + this.object.put(pos, obj); } @Override - public void put(final String name, final Phi object) { - this.enclosure.put(name, object); + public void put(final String name, final Phi obj) { + this.object.put(name, obj); } @Override public String locator() { - return this.enclosure.locator(); + return this.object.locator(); } @Override public String forma() { - return this.enclosure.forma(); + return this.object.forma(); } @Override public String φTerm() { - return this.enclosure.φTerm(); + return this.object.φTerm(); } @Override public int hashCode() { - return this.enclosure.hashCode(); + return this.object.hashCode(); } @Override @@ -149,7 +148,7 @@ public boolean equals(final Object obj) { @Override public byte[] delta() { - return new TracingWhileGetting<>(this.enclosure::delta).get(); + return new TracingWhileGetting<>(this.object::delta).get(); } /** @@ -182,18 +181,19 @@ public T get() { } /** - * Increments counter of cage in the {@link PhTracedEnclosure#DATAIZING_CAGES}. + * Increments counter of cage in the {@link PhTracedLocator#DATAIZING_CAGES}. * @return New value in the map. */ private Integer incrementCageCounter() { - return PhTracedEnclosure.DATAIZING_CAGES.compute( - PhTracedEnclosure.this.cage, (key, counter) -> { + return PhTracedLocator.DATAIZING_CAGES.compute( + PhTracedLocator.this.locator, (key, counter) -> { final int ret = this.incremented(counter); - if (ret > PhTracedEnclosure.this.depth) { + if (ret > PhTracedLocator.this.depth) { throw new ExFailure( - "The cage %s has reached the maximum nesting depth = %d", - key.φTerm(), - PhTracedEnclosure.this.depth + "The cage %s with locator %d has reached the maximum nesting depth = %d", + PhTracedLocator.this.object, + PhTracedLocator.this.locator, + PhTracedLocator.this.depth ); } return ret; @@ -219,19 +219,19 @@ private Integer incremented(final Integer number) { } /** - * Decrements counter in the {@link PhTracedEnclosure#DATAIZING_CAGES}. + * Decrements counter in the {@link PhTracedLocator#DATAIZING_CAGES}. * @param incremented Current value of counter. This argument ensures * temporal coupling with {@link TracingWhileGetting#incrementCageCounter} method. */ private void decrementCageCounter(final int incremented) { final int decremented = incremented - 1; if (decremented == 0) { - PhTracedEnclosure.DATAIZING_CAGES.remove( - PhTracedEnclosure.this.cage + PhTracedLocator.DATAIZING_CAGES.remove( + PhTracedLocator.this.locator ); } else { - PhTracedEnclosure.DATAIZING_CAGES.put( - PhTracedEnclosure.this.cage, decremented + PhTracedLocator.DATAIZING_CAGES.put( + PhTracedLocator.this.locator, decremented ); } } diff --git a/eo-runtime/src/main/java/EOorg/EOeolang/EOcage.java b/eo-runtime/src/main/java/org/eolang/PhWrite.java similarity index 52% rename from eo-runtime/src/main/java/EOorg/EOeolang/EOcage.java rename to eo-runtime/src/main/java/org/eolang/PhWrite.java index 64cdfe9923..c4a28a18b1 100644 --- a/eo-runtime/src/main/java/EOorg/EOeolang/EOcage.java +++ b/eo-runtime/src/main/java/org/eolang/PhWrite.java @@ -25,67 +25,48 @@ /* * @checkstyle PackageNameCheck (4 lines) */ -package EOorg.EOeolang; -import org.eolang.AtCage; -import org.eolang.AtSimple; -import org.eolang.AtVoid; -import org.eolang.Atom; -import org.eolang.Attr; -import org.eolang.Data; -import org.eolang.PhDefault; -import org.eolang.PhTracedEnclosure; -import org.eolang.Phi; -import org.eolang.Versionized; -import org.eolang.Volatile; -import org.eolang.XmirObject; +package org.eolang; + +import java.util.function.Function; /** - * CAGE. - * - * @since 0.17 - * @checkstyle TypeNameCheck (5 lines) + * Object that writes other object to own \rho. + * (see {@link EOorg.EOeolang.EOcage$EOnew} and {@link EOorg.EOeolang.EOmemory$EOalloc}). + * @since 0.36.0 */ -@Versionized -@Volatile -@XmirObject(oname = "cage") -public final class EOcage extends PhDefault implements Atom { +public final class PhWrite extends PhDefault implements Atom { + /** + * Attribute name. + */ + private final String attribute; + + /** + * Return value. + */ + private final Function value; /** * Ctor. * @param sigma Sigma + * @param attr Attribute name + * @param ret Return value function */ - public EOcage(final Phi sigma) { + public PhWrite( + final Phi sigma, + final String attr, + final Function ret + ) { super(sigma); - this.add("enclosure", new AtCage()); - this.add("write", new AtSimple(new Write(this))); + this.attribute = attr; + this.add(this.attribute, new AtVoid(this.attribute)); + this.value = ret; } @Override public Phi lambda() { - return new PhTracedEnclosure(this.take("enclosure"), this); + final Phi rho = this.take(Attr.RHO); + rho.put(this.attribute, this.take(this.attribute)); + return this.value.apply(rho); } - - /** - * Cage write. - * @since 0.17 - */ - @XmirObject(oname = "cage.write") - private static final class Write extends PhDefault implements Atom { - /** - * Ctor. - * @param sigma Sigma - */ - Write(final Phi sigma) { - super(sigma); - this.add("x", new AtVoid("x")); - } - - @Override - public Phi lambda() { - this.take(Attr.RHO).put("enclosure", this.take("x")); - return new Data.ToPhi(true); - } - } - } diff --git a/eo-runtime/src/test/eo/org/eolang/bytes-tests.eo b/eo-runtime/src/test/eo/org/eolang/bytes-tests.eo index 6792a9e1a1..58cd651ff2 100644 --- a/eo-runtime/src/test/eo/org/eolang/bytes-tests.eo +++ b/eo-runtime/src/test/eo/org/eolang/bytes-tests.eo @@ -460,8 +460,7 @@ # Test. [] > as-bool-is-transparent TRUE.as-bytes > b - not. > res + not. > @ eq. b.as-bool.as-bytes.< b.< - TRUE > @ diff --git a/eo-runtime/src/test/eo/org/eolang/cage-tests.eo b/eo-runtime/src/test/eo/org/eolang/cage-tests.eo index 3cf36288a5..71734fa104 100644 --- a/eo-runtime/src/test/eo/org/eolang/cage-tests.eo +++ b/eo-runtime/src/test/eo/org/eolang/cage-tests.eo @@ -27,204 +27,190 @@ +version 0.0.0 # Test. -# @todo #2931:30min Enable cage tests. The test were disabled because 1) most probably -# "EOseq" dataizes its lambda many times in PhDefault.attr method. 2) current implementation of -# cage is wrong. Need to enable the tests when it's possible. -[] > cage-tests - TRUE > @ - # Test. - [] > writes-into-cage - # Object with free attribute. - [z] > a - cage a > x - eq. > @ - seq - * - x.write - a 7 - x.z - 7 - - # Test. - [] > avoid-infinite-loop - cage > x - if - x' > copy - eq. > @ - seq - * - x.write - if TRUE 1 0 - copy.< - x.write - if TRUE copy 0 - x - 1 +[] > encages-into-cage + # Object with free attribute. + [z] > a + cage.new a > x + eq. > @ + seq > seven! + * + x.encage + a 7 + x.z + 7 - # Test. - [] > cage-nested-objects - # Dummy object. - [x] > dummy - x > @ - cage dummy > c - c' > copy - eq. > @ - seq - * - c.write (dummy 42) - copy.< - c.write (dummy copy) - c.x.x - 42 +# Test. +[] > does-not-avoid-infinite-loop + cage.new > x + if + x' > copy + try > @ + seq + * + x.encage + if TRUE 1 0 + copy.< + x.encage + if TRUE copy 0 + x + [e] + QQ.io.stdout e > @ + TRUE - # Test. - [] > dataizes-encaged-object-not-lazily-first - cage 0 > x - cage 0.plus > sum - eq. > @ - seq - * - x.write 42 - sum.write - x.plus 1 - x.write 7 - sum - 8 +# Test. +[] > dataizes-encaged-object-not-lazily-first + cage.new 0 > x + cage.new int.plus > sum + eq. > @ + seq > s! + * + x.encage 42 + sum.encage + x.plus 1 + x.encage 7 + sum + 8 - # Test. - [] > dataizes-encaged-object-lazily-second - cage 0 > x - cage 0.plus > sum - eq. > @ - seq - * - x.write 42 - sum.write - 1.plus x - x.write 7 - sum - 8 +# Test. +[] > dataizes-encaged-object-lazily-second + cage.new 0 > x + cage.new int.plus > sum + eq. > @ + seq > s! + * + x.encage 42 + sum.encage + 1.plus x + x.encage 7 + sum + 8 - # Test. - [] > dataizes-encaged-object-lazily-third - cage 0 > x - cage 0 > y - cage 0.plus > sum - eq. > @ - seq - * - x.write 42 - y.write 7 - sum.write - x.plus y - y.write 13 - x.write 4 - sum - 17 +# Test. +[] > dataizes-encaged-object-lazily-third + cage.new 0 > x + cage.new 0 > y + cage.new int.plus > sum + eq. > @ + seq > s! + * + x.encage 42 + y.encage 7 + sum.encage + x.plus y + y.encage 13 + x.encage 4 + sum + 17 - # Test. - [] > stores-abstract-object-into-cage - eq. > @ - seq - * - cage > c - [] - 112 > @ - c.@ - 112 +# Test. +[] > stores-abstract-object-into-cage + eq. > @ + seq + * + cage.new > c + [] + 112 > @ + c.@ + 112 - # Test. - [] > multi-layer-volatility - memory 0 > ma - cage a > ca - # Layer A. - [] > a - # Layer A.phi. +# Test. +[] > multi-layer-volatility + memory.alloc 0 > ma + cage.new a > ca + # Layer A. + [] > a + # Layer A.phi. + [] > @ + # Layer A.phi.phi. [] > @ - # Layer A.phi.phi. + # Layer A.phi.phi.phi. [] > @ - # Layer A.phi.phi.phi. - [] > @ - seq > @ - * - ma.write (ma.as-int.plus 1) - ma.as-int - memory 0 > mb - cage b > cb - # Layer B. - [] > b - # Layer B.phi. + seq > @ + * + ma.write (ma.as-int.plus 1) + ma.as-int + memory.alloc 0 > mb + cage.new b > cb + # Layer B. + [] > b + # Layer B.phi. + [] > @ + # Layer B.phi.phi. [] > @ - # Layer B.phi.phi. + # Layer B.phi.phi.phi. [] > @ - # Layer B.phi.phi.phi. - [] > @ - seq > z - * - mb.write (mb.as-int.plus 1) - mb.as-int - eq. > res - seq - * - ca - ca.plus 40 - seq - * - cb.z - cb.z.plus 40 - TRUE > @ + seq > z + * + mb.write (mb.as-int.plus 1) + mb.as-int + eq. > @ + seq > s1! + * + ca + ca.plus 40 + seq > s2! + * + cb.z + cb.z.plus 40 - # Test. - [] > infinite-loop-check - # Recursive sum object. - [value] > pyint - # Add. - [y] > add - pyint (^.value.plus y.value) > @ - cage pyint > x - cage > tmp - x.add - eq. > @ - seq - * - x.write - pyint 0 - tmp.write - x.add (pyint 1) - QQ.io.stdout - tmp.value +# Test. +[] > infinite-loop-check + # Recursive sum object. + [value] > pyint + # Add. + [y] > add + pyint (^.value.plus y.value) > @ + cage.new pyint > x + cage.new > tmp + x.add + eq. > @ + seq + * + x.encage + pyint 0 + tmp.encage + x.add (pyint 1) + QQ.io.stdout tmp.value - 1 + tmp.value + 1 - # Test. - [] > catches-writing-objects-of-different-types - cage 5 > cge - eq. > @ - seq +# Test. +[] > catches-encaging-objects-of-different-formas + cage.new 5 > cge + seq > @ + * + try + cge.encage "Hello world" + [e] + cge.encage 10 > @ + nop + cge.eq 10 + +# Check that cage stack leads to error. Just prints the error +# message if passes. +[] > catches-stack-overflow + cage.new > cge + int.plus + try > @ + [] + seq > @ * - try - cge.write "Hello world" - [e] - cge.write 10 > @ - nop - cge.eq 10 - TRUE + cge.write + 0.plus cge + cge + FALSE + [stack-overflow-message] + QQ.io.stdout > @ + stack-overflow-message + FALSE - # Check that cage stack leads to error. Just prints the error - # message if passes. - [] > catches-stack-overflow - cage > cge - 0.plus - try > @ - [] - seq > @ - * - cge.write - 0.plus cge - cge - FALSE - [stack-overflow-message] - QQ.io.stdout > @ - stack-overflow-message - [] - FALSE > @ +# Test. +[] > applies-after-retrieval + # Func. + [x] > func + 2.plus x > @ + cage.new func > c + eq. > @ + c.it 5 + 7 diff --git a/eo-runtime/src/test/eo/org/eolang/runtime-tests.eo b/eo-runtime/src/test/eo/org/eolang/runtime-tests.eo index 1d133e0ef7..3c02634484 100644 --- a/eo-runtime/src/test/eo/org/eolang/runtime-tests.eo +++ b/eo-runtime/src/test/eo/org/eolang/runtime-tests.eo @@ -28,10 +28,6 @@ +version 0.0.0 # Test. -# @todo #2931:30min Enable runtime tests. The tests were disabled because they stopped working -# when \rho attribute became immutable. Need to find out what's going on and enable them. -# Tests: refers-to-inner-vars-correctly, makes-shallow-copy, calling-caged-function, -# rho-of-add-should-not-change [] > understands-this-correctly # Abstract a. [x] > a @@ -117,19 +113,19 @@ 1 # Test. -[] > rho-of-add-should-not-change - memory 0 > f1 - cage 0 > f2 - memory 0 > f0 - nop > res - seq - * - f0.write 0 - f1.write 1 - f2.write (f0.plus f1) - f1.write f2 - TRUE - TRUE > @ +[] > writes-cage-to-memory + memory.alloc 0 > f1 + cage.new int.plus > f2 + memory.alloc 0 > f0 + seq > @ + * + f0.write 1 + f1.write 2 + f2.encage ((int f0).plus f1) + f1.write f2 + eq. + f1 + 3 # Test. [] > positive-object-vertices @@ -210,22 +206,19 @@ # Test. [] > refers-to-inner-vars-correctly - memory 0 > go - eq. > res - seq - * - go.write TRUE - go.as-bool.while - [i] - memory 0 > m - seq > @ - * - 42 > x - m.write x - go.write FALSE - TRUE - TRUE - nop > @ + memory.alloc 0 > go + seq > @ + * + go.write TRUE + while + go.as-bool + [i] + memory.alloc 0 > m + seq > @ + * + m.write 42 + go.write FALSE + TRUE # Test. [] > named-inner-abstract-object @@ -237,18 +230,15 @@ # Test. [] > calling-caged-function - cage 0 > h # Func. - [x] > func - 2.plus x > @ - nop > res - eq. - seq - * - h.write func - h.@ 8 - 10 - TRUE > @ + [] > func + # Inner object. + [x] > @ + 2.plus x > @ + cage.new func > h + eq. > @ + h.@ 8 + 10 # Test. [] > app-that-calls-func @@ -329,10 +319,9 @@ # Test. [] > compares-two-foreign-objects stdout.< > vtx - nop > @ - and. - vtx.eq QQ.io.stdout.< - vtx.eq Q.org.eolang.io.stdout.< + and. > @ + vtx.eq QQ.io.stdout.< + vtx.eq Q.org.eolang.io.stdout.< # Test. [] > compares-two-local-objects @@ -359,25 +348,6 @@ num 64 -# Test. -[] > makes-shallow-copy - # A. - [] > a - memory' > v - # B. - [] > b - a > @ - b' > b1 - b' > b2 - seq > res - * - b1.v.write 0 - b2.v.write 1 - eq. - b1.v - 1 - TRUE > @ - # Test. [] > copy-object-with-dot # Book. diff --git a/eo-runtime/src/test/java/EOorg/EOeolang/EOcageTest.java b/eo-runtime/src/test/java/EOorg/EOeolang/EOcageTest.java index aff7219576..fc10d3d50a 100644 --- a/eo-runtime/src/test/java/EOorg/EOeolang/EOcageTest.java +++ b/eo-runtime/src/test/java/EOorg/EOeolang/EOcageTest.java @@ -37,7 +37,7 @@ import org.eolang.PhCopy; import org.eolang.PhDefault; import org.eolang.PhMethod; -import org.eolang.PhTracedEnclosure; +import org.eolang.PhTracedLocator; import org.eolang.PhWith; import org.eolang.Phi; import org.hamcrest.MatcherAssert; @@ -45,22 +45,19 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.parallel.Execution; import org.junit.jupiter.api.parallel.ExecutionMode; /** - * Test case for {@link EOcage}. + * Test cases for {@link EOcage} and {@link EOcage$EOnew}. * @since 0.19 */ final class EOcageTest { - @Test - void writesAndReads() { - final Phi cage = new EOcage(Phi.Φ); - EOcageTest.writeTo(cage, new Data.ToPhi(1L)); + void encagesViaApplication() { + final Phi cage = EOcageTest.encaged(new Data.ToPhi(1L)); MatcherAssert.assertThat( new Dataized(cage).take(Long.class), Matchers.equalTo(1L) @@ -68,70 +65,27 @@ void writesAndReads() { } @Test - void checksThatEmptyCageHasIdentity() { - final Phi cage = new EOcage(Phi.Φ); - MatcherAssert.assertThat( - new Dataized(cage.take(Attr.VERTEX)).take(Long.class), - Matchers.greaterThan(0L) - ); - } - - @Test - void writesItselfToItself() { - final Phi cage = new EOcage(Phi.Φ); - EOcageTest.writeTo( - cage, - new PhWith( - new EOcage(Phi.Φ), 0, new Data.ToPhi(1L) - ) - ); - final Phi first = cage.copy(); - EOcageTest.writeTo(cage, first); - final Phi second = cage.copy(); - EOcageTest.writeTo(cage, second); + void encagesAndFrees() { + final Phi cage = EOcageTest.encaged(new Data.ToPhi(1L)); + EOcageTest.encageTo(cage, new Data.ToPhi(2L)); MatcherAssert.assertThat( new Dataized(cage).take(Long.class), - Matchers.equalTo(1L) + Matchers.equalTo(2L) ); } - // [] > test - // cage 0 > c - // [x] > dummy - // x > @ - // seq > @ - // * - // c.write (dummy 1) - // c.write (dummy c') - // c.x.x.eq 1 @Test - void writesDummyToItself() { - final Phi cage = new EOcage(Phi.Φ); - new Dataized( - new PhWith( - cage.take("write").copy(), - 0, new PhWith(new EOcageTest.Dummy(Phi.Φ), 0, new Data.ToPhi(1L)) - ) - ).take(); - new Dataized( - new PhWith( - cage.take("write").copy(), - 0, new PhWith(new EOcageTest.Dummy(Phi.Φ), 0, cage.copy()) - ) - ).take(); + void checksThatEmptyCageHasIdentity() { + final Phi cage = Phi.Φ.take("org.eolang.cage"); MatcherAssert.assertThat( - new Dataized( - cage.take("x").take("x") - ).take(Long.class), - Matchers.equalTo(1L) + new Dataized(cage.take(Attr.VERTEX)).take(Long.class), + Matchers.greaterThan(0L) ); } @Test void overwritesCagedObject() { - final Phi cage = new EOcage(Phi.Φ); - EOcageTest.writeTo( - cage, + final Phi cage = EOcageTest.encaged( new PhWith( new EOcageTest.Dummy(Phi.Φ), 0, new Data.ToPhi(1L) @@ -141,7 +95,7 @@ void overwritesCagedObject() { new Dataized(new PhMethod(cage, "x")).take(Long.class), Matchers.equalTo(1L) ); - EOcageTest.writeTo( + EOcageTest.encageTo( cage, new PhWith( new EOcageTest.Dummy(Phi.Φ), @@ -155,31 +109,24 @@ void overwritesCagedObject() { } @Test - void makesTrueCopy() { - final Phi first = new EOcage(Phi.Φ); - first.put(0, new Data.ToPhi(1L)); + void encagesObjectOnCopy() { + final Phi first = EOcageTest.encaged(new Data.ToPhi(1L)); final Phi second = first.copy(); - new Dataized( - new PhWith( - second.take("write"), - "x", new Data.ToPhi(2L) - ) - ).take(); + EOcageTest.encageTo(second, new Data.ToPhi(2L)); MatcherAssert.assertThat( new Dataized(first).take(Long.class), - Matchers.equalTo(1L) + Matchers.equalTo(2L) ); } @Test void writesAndRewritesPrimitive() { - final Phi cage = new EOcage(Phi.Φ); - EOcageTest.writeTo(cage, new Data.ToPhi(1L)); + final Phi cage = EOcageTest.encaged(new Data.ToPhi(1L)); MatcherAssert.assertThat( new Dataized(cage).take(Long.class), Matchers.equalTo(1L) ); - EOcageTest.writeTo(cage, new Data.ToPhi(5L)); + EOcageTest.encageTo(cage, new Data.ToPhi(5L)); MatcherAssert.assertThat( new Dataized(cage).take(Long.class), Matchers.equalTo(5L) @@ -188,11 +135,10 @@ void writesAndRewritesPrimitive() { @Test void doesNotWritePrimitivesFormedDifferently() { - final Phi cage = new EOcage(Phi.Φ); - EOcageTest.writeTo(cage, new Data.ToPhi(1L)); + final Phi cage = EOcageTest.encaged(new Data.ToPhi(1L)); Assertions.assertThrows( EOerror.ExError.class, - () -> EOcageTest.writeTo(cage, new Data.ToPhi("Hello world")) + () -> EOcageTest.encageTo(cage, new Data.ToPhi("Hello world")) ); } @@ -204,11 +150,10 @@ void doesNotWriteBoundedMethod() { "x", new Data.ToPhi(5L) ); - final Phi cage = new EOcage(Phi.Φ); - EOcageTest.writeTo(cage, five); + final Phi cage = EOcageTest.encaged(five); Assertions.assertThrows( EOerror.ExError.class, - () -> EOcageTest.writeTo(cage, ten) + () -> EOcageTest.encageTo(cage, ten) ); } @@ -216,19 +161,36 @@ void doesNotWriteBoundedMethod() { void writesBoundedCopyOfTheSameBase() { final Phi dummy = new Dummy(Phi.Φ); Assertions.assertDoesNotThrow( - () -> EOcageTest.writeTo( - new PhWith(new EOcage(Phi.Φ), 0, dummy), + () -> EOcageTest.encageTo( + EOcageTest.encaged(dummy), new PhWith(new PhCopy(dummy), "x", new Data.ToPhi("Hello world")) ) ); } - private static void writeTo(final Phi cage, final Phi obj) { - final Phi write = cage.take("write").copy(); + /** + * Encage given object to given cage. + * @param cage Cage + * @param obj Object + */ + private static void encageTo(final Phi cage, final Phi obj) { + final Phi write = cage.take("encage").copy(); write.put(0, obj); new Dataized(write).take(); } + /** + * Encaged object. + * @param obj Object to put + * @return Cage.new object + */ + private static Phi encaged(final Phi obj) { + final Phi cage = Phi.Φ.take("org.eolang.cage"); + final Phi encaged = cage.take("new").copy(); + encaged.put(0, obj); + return encaged; + } + /** * Cases to test behaviour of cage with recursion. * @since 0.1 @@ -245,19 +207,44 @@ class RecursionTests { @BeforeEach void setDepth() { System.setProperty( - PhTracedEnclosure.MAX_CAGE_RECURSION_DEPTH_PROPERTY_NAME, String.valueOf(MAX_DEPTH) + PhTracedLocator.MAX_CAGE_RECURSION_DEPTH_PROPERTY_NAME, String.valueOf(MAX_DEPTH) ); } @AfterEach void clearDepth() { - System.clearProperty(PhTracedEnclosure.MAX_CAGE_RECURSION_DEPTH_PROPERTY_NAME); + System.clearProperty(PhTracedLocator.MAX_CAGE_RECURSION_DEPTH_PROPERTY_NAME); + } + + // [] > test + // [x] > dummy + // x > @ + // cage.new (dummy 1) > c + // seq > @ + // * + // c.write (dummy c') + // c.x.x.x # fail + @Test + void rewritesItselfToItselfViaDummy() { + System.setProperty( + PhTracedLocator.MAX_CAGE_RECURSION_DEPTH_PROPERTY_NAME, "2" + ); + final Phi cage = EOcageTest.encaged( + new PhWith(new EOcageTest.Dummy(Phi.Φ), 0, new Data.ToPhi(1L)) + ); + EOcageTest.encageTo(cage, new PhWith(new EOcageTest.Dummy(Phi.Φ), 0, cage.copy())); + Assertions.assertThrows( + ExAbstract.class, + () -> new Dataized( + cage.take("x").take("x").take("x") + ).take(Long.class) + ); } @Test void throwsExceptionIfRecursion() { - final Phi cage = new EOcage(Phi.Φ); - writeTo(cage, cage); + final Phi cage = Phi.Φ.take("org.eolang.cage").take("new").copy(); + EOcageTest.encageTo(cage, cage); Assertions.assertThrows( ExAbstract.class, () -> new Dataized(cage).take(), @@ -267,8 +254,8 @@ void throwsExceptionIfRecursion() { @Test void doesNotThrowExceptionIfSmallDepth() { - final Phi cage = new EOcage(Phi.Φ); - EOcageTest.writeTo( + final Phi cage = Phi.Φ.take("org.eolang.cage").take("new").copy(); + EOcageTest.encageTo( cage, new RecursiveDummy(EOcageTest.RecursionTests.MAX_DEPTH / 2, cage) ); @@ -276,8 +263,8 @@ void doesNotThrowExceptionIfSmallDepth() { () -> new Dataized(cage).take(), String.format( "We expect that dataizing of nested cage which recursion depth is less than property %s = %s does not throw %s", - PhTracedEnclosure.MAX_CAGE_RECURSION_DEPTH_PROPERTY_NAME, - System.getProperty(PhTracedEnclosure.MAX_CAGE_RECURSION_DEPTH_PROPERTY_NAME), + PhTracedLocator.MAX_CAGE_RECURSION_DEPTH_PROPERTY_NAME, + System.getProperty(PhTracedLocator.MAX_CAGE_RECURSION_DEPTH_PROPERTY_NAME), ExAbstract.class ) ); @@ -288,17 +275,17 @@ void doesNotThrowExceptionIfSmallDepth() { */ @Test void doesNotThrowExceptionIfMaxDepth() { - final Phi cage = new EOcage(Phi.Φ); - writeTo( + final Phi cage = Phi.Φ.take("org.eolang.cage").take("new").copy(); + EOcageTest.encageTo( cage, - new RecursiveDummy(MAX_DEPTH, cage) + new RecursiveDummy(EOcageTest.RecursionTests.MAX_DEPTH, cage) ); Assertions.assertDoesNotThrow( () -> new Dataized(cage).take(), String.format( "We expect that dataizing of nested cage which recursion depth is equal to property %s = %s does not throw %s", - PhTracedEnclosure.MAX_CAGE_RECURSION_DEPTH_PROPERTY_NAME, - System.getProperty(PhTracedEnclosure.MAX_CAGE_RECURSION_DEPTH_PROPERTY_NAME), + PhTracedLocator.MAX_CAGE_RECURSION_DEPTH_PROPERTY_NAME, + System.getProperty(PhTracedLocator.MAX_CAGE_RECURSION_DEPTH_PROPERTY_NAME), ExAbstract.class ) ); @@ -306,8 +293,8 @@ void doesNotThrowExceptionIfMaxDepth() { @Test void throwsExceptionIfBigDepth() { - final Phi cage = new EOcage(Phi.Φ); - writeTo( + final Phi cage = Phi.Φ.take("org.eolang.cage").take("new").copy(); + EOcageTest.encageTo( cage, new RecursiveDummy(EOcageTest.RecursionTests.MAX_DEPTH + 1, cage) ); @@ -316,8 +303,8 @@ void throwsExceptionIfBigDepth() { () -> new Dataized(cage).take(), String.format( "We expect that dataizing of nested cage which recursion depth is more than property %s = %s does not throw %s", - PhTracedEnclosure.MAX_CAGE_RECURSION_DEPTH_PROPERTY_NAME, - System.getProperty(PhTracedEnclosure.MAX_CAGE_RECURSION_DEPTH_PROPERTY_NAME), + PhTracedLocator.MAX_CAGE_RECURSION_DEPTH_PROPERTY_NAME, + System.getProperty(PhTracedLocator.MAX_CAGE_RECURSION_DEPTH_PROPERTY_NAME), ExAbstract.class ) ); @@ -349,9 +336,7 @@ private final class RecursiveDummy extends PhDefault implements Atom { * @param depth Depth. * @param cage Cage. */ - RecursiveDummy( - final int depth, final Phi cage - ) { + RecursiveDummy(final int depth, final Phi cage) { this.depth = depth; this.cage = cage; this.counter = new AtomicReference<>(0); @@ -375,7 +360,7 @@ public Phi lambda() { * Dummy Phi. * @since 1.0 */ - public static final class Dummy extends PhDefault { + private static final class Dummy extends PhDefault { /** * Ctor. * @param sigma Sigma diff --git a/eo-runtime/src/test/java/EOorg/EOeolang/EOmemoryTest.java b/eo-runtime/src/test/java/EOorg/EOeolang/EOmemoryTest.java index ccdec0ab19..10d58586c3 100644 --- a/eo-runtime/src/test/java/EOorg/EOeolang/EOmemoryTest.java +++ b/eo-runtime/src/test/java/EOorg/EOeolang/EOmemoryTest.java @@ -40,7 +40,7 @@ import org.junit.jupiter.api.Test; /** - * Test case for {@link EOmemory}. + * Test case for {@link EOmemory} and {@link EOmemory$EOalloc}. * * @since 0.1 */