From c69465640fc1f08bb186e23d133d6c495e04daf8 Mon Sep 17 00:00:00 2001 From: h1alexbel Date: Fri, 17 Oct 2025 16:48:33 +0300 Subject: [PATCH 1/8] bug(#4504): compacts base resolution via XSL --- .../org/eolang/snippets/compact-array.yaml | 18 ++++++++++ .../maven/transpile-packs/compact-array.yaml | 24 +++++++++++++ .../org/eolang/parser/CompactArrayFqn.java | 14 +++----- .../main/java/org/eolang/parser/EoSyntax.java | 3 ++ .../java/org/eolang/parser/XeEoListener.java | 23 ++++++++++++ .../eolang/parser/parse/resolve-compacts.xsl | 36 +++++++++++++++++++ .../eolang/parser/CompactArrayFqnTest.java | 2 +- .../parse/validate-resolve-before-stars.yaml | 3 +- ...compact-array-with-defined-first-part.yaml | 16 +++++++++ .../parser/eo-syntax/compact-array.yaml | 17 +++++++++ .../eo-syntax/compact-sprintf-aliased.yaml | 18 ++++++++++ ...red-array-with-composite-name-aliased.yaml | 16 +++++++++ .../sugared-array-with-composite-name.yaml | 4 +-- 13 files changed, 181 insertions(+), 13 deletions(-) create mode 100644 eo-integration-tests/src/test/resources/org/eolang/snippets/compact-array.yaml create mode 100644 eo-maven-plugin/src/test/resources/org/eolang/maven/transpile-packs/compact-array.yaml create mode 100644 eo-parser/src/main/resources/org/eolang/parser/parse/resolve-compacts.xsl create mode 100644 eo-parser/src/test/resources/org/eolang/parser/eo-syntax/compact-array-with-defined-first-part.yaml create mode 100644 eo-parser/src/test/resources/org/eolang/parser/eo-syntax/compact-array.yaml create mode 100644 eo-parser/src/test/resources/org/eolang/parser/eo-syntax/compact-sprintf-aliased.yaml create mode 100644 eo-parser/src/test/resources/org/eolang/parser/eo-syntax/sugared-array-with-composite-name-aliased.yaml diff --git a/eo-integration-tests/src/test/resources/org/eolang/snippets/compact-array.yaml b/eo-integration-tests/src/test/resources/org/eolang/snippets/compact-array.yaml new file mode 100644 index 00000000000..b99716210f2 --- /dev/null +++ b/eo-integration-tests/src/test/resources/org/eolang/snippets/compact-array.yaml @@ -0,0 +1,18 @@ +# SPDX-FileCopyrightText: Copyright (c) 2016-2025 Objectionary.com +# SPDX-License-Identifier: MIT +--- +# yamllint disable rule:line-length +out: + - ".*Hello, 上海.*" +file: program.eo +args: ["org.eolang.snippets.program", "上海"] +target: "eoc" +eo: | + +alias org.eolang.io.stdout + +package org.eolang.snippets + + [args] > program + io.stdout > @ + tt.sprintf *1 + "Hello, %s\n" + args.at 0 diff --git a/eo-maven-plugin/src/test/resources/org/eolang/maven/transpile-packs/compact-array.yaml b/eo-maven-plugin/src/test/resources/org/eolang/maven/transpile-packs/compact-array.yaml new file mode 100644 index 00000000000..a55414dda2a --- /dev/null +++ b/eo-maven-plugin/src/test/resources/org/eolang/maven/transpile-packs/compact-array.yaml @@ -0,0 +1,24 @@ +# SPDX-FileCopyrightText: Copyright (c) 2016-2025 Objectionary.com +# SPDX-License-Identifier: MIT +--- +# yamllint disable rule:line-length +sheets: + - /org/eolang/maven/transpile/set-locators.xsl + - /org/eolang/maven/transpile/set-original-names.xsl + - /org/eolang/maven/transpile/classes.xsl + - /org/eolang/maven/transpile/package.xsl + - /org/eolang/maven/transpile/attrs.xsl + - /org/eolang/maven/transpile/data.xsl + - /org/eolang/maven/transpile/to-java.xsl +asserts: + - /object[not(errors)] + - //java[contains(text(), 'base="Φ.org.eolang.tt.sprintf"')] +input: | + +alias org.eolang.io.stdout + +package org.eolang.snippets + + [args] > program + io.stdout > @ + tt.sprintf *1 + "Hello, %s\n" + args.at 0 diff --git a/eo-parser/src/main/java/org/eolang/parser/CompactArrayFqn.java b/eo-parser/src/main/java/org/eolang/parser/CompactArrayFqn.java index e8ac5d03242..9a8183065c1 100644 --- a/eo-parser/src/main/java/org/eolang/parser/CompactArrayFqn.java +++ b/eo-parser/src/main/java/org/eolang/parser/CompactArrayFqn.java @@ -46,17 +46,13 @@ public String asString() { .map(ParseTree::getText) .collect(Collectors.joining(".")); final String fqn; - if (this.context.HOME() == null) { - fqn = name; - } else { + if (this.context.HOME() == null && this.context.XI() == null) { + fqn = String.format("@compact:%s", name); + } else if (this.context.HOME() != null && this.context.XI() == null) { fqn = String.format("Φ.org.eolang.%s", name); - } - final String base; - if (this.context.XI() == null) { - base = fqn; } else { - base = String.format("ξ.%s", fqn); + fqn = String.format("ξ.%s", name); } - return base; + return fqn; } } diff --git a/eo-parser/src/main/java/org/eolang/parser/EoSyntax.java b/eo-parser/src/main/java/org/eolang/parser/EoSyntax.java index 3d819a42074..10cbf3623b8 100644 --- a/eo-parser/src/main/java/org/eolang/parser/EoSyntax.java +++ b/eo-parser/src/main/java/org/eolang/parser/EoSyntax.java @@ -98,6 +98,9 @@ public final class EoSyntax implements Syntax { "/org/eolang/parser/parse/expand-qqs.xsl", "/org/eolang/parser/parse/expand-aliases.xsl", "/org/eolang/parser/parse/resolve-aliases.xsl", + "/org/eolang/parser/parse/resolve-compacts.xsl", + "/org/eolang/parser/parse/validate-before-stars.xsl", + "/org/eolang/parser/parse/resolve-before-stars.xsl", "/org/eolang/parser/parse/add-default-package.xsl", "/org/eolang/parser/parse/roll-bases.xsl", "/org/eolang/parser/parse/cti-adds-errors.xsl", diff --git a/eo-parser/src/main/java/org/eolang/parser/XeEoListener.java b/eo-parser/src/main/java/org/eolang/parser/XeEoListener.java index cffdb8963b8..d5ac48ca71b 100644 --- a/eo-parser/src/main/java/org/eolang/parser/XeEoListener.java +++ b/eo-parser/src/main/java/org/eolang/parser/XeEoListener.java @@ -7,6 +7,8 @@ import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.function.Supplier; @@ -584,6 +586,27 @@ public void enterCompactArray(final EoParser.CompactArrayContext ctx) { .prop("before-star", count); } + private static List aliases(final EoParser.ProgramContext program) { + final List result; + if (program.metas() == null) { + result = Collections.emptyList(); + } else { + result = Arrays.stream(program.metas().getText().split("\n")) + .filter(m -> m.startsWith("+alias")) + .map(a -> a.replace("+alias", "")) + .collect(Collectors.toList()); + } + return result; + } + + private static EoParser.ProgramContext programContext(final ParserRuleContext ctx) { + ParserRuleContext p = ctx; + while (p.getParent() != null) { + p = (ParserRuleContext) p.getParent(); + } + return (EoParser.ProgramContext) p; + } + @Override public void exitCompactArray(final EoParser.CompactArrayContext ctx) { this.objects.leave(); diff --git a/eo-parser/src/main/resources/org/eolang/parser/parse/resolve-compacts.xsl b/eo-parser/src/main/resources/org/eolang/parser/parse/resolve-compacts.xsl new file mode 100644 index 00000000000..198dcd16b24 --- /dev/null +++ b/eo-parser/src/main/resources/org/eolang/parser/parse/resolve-compacts.xsl @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/eo-parser/src/test/java/org/eolang/parser/CompactArrayFqnTest.java b/eo-parser/src/test/java/org/eolang/parser/CompactArrayFqnTest.java index 0eb28412963..1b28e726559 100644 --- a/eo-parser/src/test/java/org/eolang/parser/CompactArrayFqnTest.java +++ b/eo-parser/src/test/java/org/eolang/parser/CompactArrayFqnTest.java @@ -19,7 +19,7 @@ final class CompactArrayFqnTest { @ParameterizedTest @CsvSource( { - "foo *1,foo", + "foo *1,@compact:foo", "QQ.foo.bar *42,Φ.org.eolang.foo.bar", "QQ.nan *52,Φ.org.eolang.nan", "$.seq *1,ξ.seq" diff --git a/eo-parser/src/test/resources/org/eolang/parser/eo-packs/parse/validate-resolve-before-stars.yaml b/eo-parser/src/test/resources/org/eolang/parser/eo-packs/parse/validate-resolve-before-stars.yaml index 10aa09a77d7..71d5979a7d0 100644 --- a/eo-parser/src/test/resources/org/eolang/parser/eo-packs/parse/validate-resolve-before-stars.yaml +++ b/eo-parser/src/test/resources/org/eolang/parser/eo-packs/parse/validate-resolve-before-stars.yaml @@ -3,6 +3,7 @@ --- # yamllint disable rule:line-length sheets: + - /org/eolang/parser/parse/resolve-compacts.xsl - /org/eolang/parser/parse/validate-before-stars.xsl - /org/eolang/parser/parse/resolve-before-stars.xsl asserts: @@ -10,7 +11,7 @@ asserts: - //o[@name='first' and count(o)=1]/o[@base='Φ.org.eolang.tuple' and @star and count(o)=2] - //o[@name='second' and count(o)=2]/o[position()=2 and @base='Φ.org.eolang.tuple' and @star and count(o)=2] - //o[@name='third' and count(o)=3]/o[position()=3 and @base='Φ.org.eolang.tuple' and @star and count(o)=1] - - //o[@name='fourth' and count(o)=2]/o[@base='sprintf' and count(o)=1]/o[@base='Φ.org.eolang.tuple' and @star and count(o)=2] + - //o[@name='fourth' and count(o)=2]/o[@base='Φ.org.eolang.sprintf' and count(o)=1]/o[@base='Φ.org.eolang.tuple' and @star and count(o)=2] - //o[@name='fourth']/o[@base='Φ.org.eolang.tuple' and @star and count(o)=1] - /object[count(//o[@before-star])=0] input: | diff --git a/eo-parser/src/test/resources/org/eolang/parser/eo-syntax/compact-array-with-defined-first-part.yaml b/eo-parser/src/test/resources/org/eolang/parser/eo-syntax/compact-array-with-defined-first-part.yaml new file mode 100644 index 00000000000..487e9a35e5c --- /dev/null +++ b/eo-parser/src/test/resources/org/eolang/parser/eo-syntax/compact-array-with-defined-first-part.yaml @@ -0,0 +1,16 @@ +# SPDX-FileCopyrightText: Copyright (c) 2016-2025 Objectionary.com +# SPDX-License-Identifier: MIT +--- +# yamllint disable rule:line-length +sheets: [] +asserts: + - /object[not(errors)] + - //o[@base='foo.bar']/o[@base='Φ.org.eolang.x'] + - //o[@base='foo.bar']//o[@base='Φ.org.eolang.y'] +input: | + # No comments. + [] > app + boom > foo + foo.bar *1 > @ + x + y diff --git a/eo-parser/src/test/resources/org/eolang/parser/eo-syntax/compact-array.yaml b/eo-parser/src/test/resources/org/eolang/parser/eo-syntax/compact-array.yaml new file mode 100644 index 00000000000..ce48af021ae --- /dev/null +++ b/eo-parser/src/test/resources/org/eolang/parser/eo-syntax/compact-array.yaml @@ -0,0 +1,17 @@ +# SPDX-FileCopyrightText: Copyright (c) 2016-2025 Objectionary.com +# SPDX-License-Identifier: MIT +--- +# yamllint disable rule:line-length +sheets: [] +asserts: + - /object[not(errors)] + - //o[@base='Φ.org.eolang.tt.sprintf'] +input: | + +alias org.eolang.io.stdout + +package org.eolang.snippets + + [args] > program + io.stdout > @ + tt.sprintf *1 + "Hello, %s\n" + args.at 0 diff --git a/eo-parser/src/test/resources/org/eolang/parser/eo-syntax/compact-sprintf-aliased.yaml b/eo-parser/src/test/resources/org/eolang/parser/eo-syntax/compact-sprintf-aliased.yaml new file mode 100644 index 00000000000..02598cc96e0 --- /dev/null +++ b/eo-parser/src/test/resources/org/eolang/parser/eo-syntax/compact-sprintf-aliased.yaml @@ -0,0 +1,18 @@ +# SPDX-FileCopyrightText: Copyright (c) 2016-2025 Objectionary.com +# SPDX-License-Identifier: MIT +--- +# yamllint disable rule:line-length +sheets: [] +asserts: + - /object[not(errors)] + - //o[@base='Φ.org.eolang.tt.sprintf']/o[@base='Φ.org.eolang.string'] +input: | + +alias org.eolang.io.stdout + +alias org.eolang.tt.sprintf + + # No comments. + [args] > simple + stdout > @ + sprintf *1 + "Hello, %s" + args.at 0 diff --git a/eo-parser/src/test/resources/org/eolang/parser/eo-syntax/sugared-array-with-composite-name-aliased.yaml b/eo-parser/src/test/resources/org/eolang/parser/eo-syntax/sugared-array-with-composite-name-aliased.yaml new file mode 100644 index 00000000000..236061733f9 --- /dev/null +++ b/eo-parser/src/test/resources/org/eolang/parser/eo-syntax/sugared-array-with-composite-name-aliased.yaml @@ -0,0 +1,16 @@ +# SPDX-FileCopyrightText: Copyright (c) 2016-2025 Objectionary.com +# SPDX-License-Identifier: MIT +--- +# yamllint disable rule:line-length +sheets: [] +asserts: + - /object[not(errors)] + - //o[@base='Φ.org.eolang.foo.bar']/o[@base='Φ.org.eolang.x'] + - //o[@base='Φ.org.eolang.foo.bar']//o[@base='Φ.org.eolang.y'] +input: | + +alias org.eolang.foo.bar + + [] > app + bar *1 > @ + x + y diff --git a/eo-parser/src/test/resources/org/eolang/parser/eo-syntax/sugared-array-with-composite-name.yaml b/eo-parser/src/test/resources/org/eolang/parser/eo-syntax/sugared-array-with-composite-name.yaml index cbe163e71ab..39b8c1e99a5 100644 --- a/eo-parser/src/test/resources/org/eolang/parser/eo-syntax/sugared-array-with-composite-name.yaml +++ b/eo-parser/src/test/resources/org/eolang/parser/eo-syntax/sugared-array-with-composite-name.yaml @@ -5,8 +5,8 @@ sheets: [] asserts: - /object[not(errors)] - - //o[@base='foo.bar']/o[@base='Φ.org.eolang.x'] - - //o[@base='foo.bar']//o[@base='Φ.org.eolang.y'] + - //o[@base='Φ.org.eolang.foo.bar']/o[@base='Φ.org.eolang.x'] + - //o[@base='Φ.org.eolang.foo.bar']//o[@base='Φ.org.eolang.y'] input: | # No comments. [] > app From ce56e1d9fb5679b7ef61919b0823e99872352153 Mon Sep 17 00:00:00 2001 From: h1alexbel Date: Fri, 17 Oct 2025 16:59:34 +0300 Subject: [PATCH 2/8] bug(#4504): clean for qulice --- .../java/org/eolang/parser/XeEoListener.java | 23 ------------------- 1 file changed, 23 deletions(-) diff --git a/eo-parser/src/main/java/org/eolang/parser/XeEoListener.java b/eo-parser/src/main/java/org/eolang/parser/XeEoListener.java index d5ac48ca71b..cffdb8963b8 100644 --- a/eo-parser/src/main/java/org/eolang/parser/XeEoListener.java +++ b/eo-parser/src/main/java/org/eolang/parser/XeEoListener.java @@ -7,8 +7,6 @@ import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.function.Supplier; @@ -586,27 +584,6 @@ public void enterCompactArray(final EoParser.CompactArrayContext ctx) { .prop("before-star", count); } - private static List aliases(final EoParser.ProgramContext program) { - final List result; - if (program.metas() == null) { - result = Collections.emptyList(); - } else { - result = Arrays.stream(program.metas().getText().split("\n")) - .filter(m -> m.startsWith("+alias")) - .map(a -> a.replace("+alias", "")) - .collect(Collectors.toList()); - } - return result; - } - - private static EoParser.ProgramContext programContext(final ParserRuleContext ctx) { - ParserRuleContext p = ctx; - while (p.getParent() != null) { - p = (ParserRuleContext) p.getParent(); - } - return (EoParser.ProgramContext) p; - } - @Override public void exitCompactArray(final EoParser.CompactArrayContext ctx) { this.objects.leave(); From 06d878a142bf682f65ed2ba6d48fd20fbb9b8a1f Mon Sep 17 00:00:00 2001 From: h1alexbel Date: Fri, 17 Oct 2025 17:07:20 +0300 Subject: [PATCH 3/8] bug(#4504): copyright, unused tail --- .../resources/org/eolang/parser/parse/resolve-compacts.xsl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/eo-parser/src/main/resources/org/eolang/parser/parse/resolve-compacts.xsl b/eo-parser/src/main/resources/org/eolang/parser/parse/resolve-compacts.xsl index 198dcd16b24..4de781ccd2c 100644 --- a/eo-parser/src/main/resources/org/eolang/parser/parse/resolve-compacts.xsl +++ b/eo-parser/src/main/resources/org/eolang/parser/parse/resolve-compacts.xsl @@ -1,4 +1,8 @@ + From d845d29ef88a591b46bf349abfff9d1c14b39612 Mon Sep 17 00:00:00 2001 From: h1alexbel Date: Fri, 17 Oct 2025 17:29:28 +0300 Subject: [PATCH 7/8] bug(#4504): change alias selection from part[2] to part[last()] for dynamic alias resolution --- .../main/resources/org/eolang/parser/parse/resolve-compacts.xsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eo-parser/src/main/resources/org/eolang/parser/parse/resolve-compacts.xsl b/eo-parser/src/main/resources/org/eolang/parser/parse/resolve-compacts.xsl index eca9248d08d..b0ea58c940c 100644 --- a/eo-parser/src/main/resources/org/eolang/parser/parse/resolve-compacts.xsl +++ b/eo-parser/src/main/resources/org/eolang/parser/parse/resolve-compacts.xsl @@ -18,7 +18,7 @@ - + From 1d8a837716eb10008413bd94eeba4bd0cfff72d0 Mon Sep 17 00:00:00 2001 From: h1alexbel Date: Wed, 22 Oct 2025 13:35:18 +0300 Subject: [PATCH 8/8] bug(#4504): remove @compact prefix and integrate compact resolution into build-fqns.xsl --- .../org/eolang/parser/CompactArrayFqn.java | 2 +- .../main/java/org/eolang/parser/EoSyntax.java | 1 - .../org/eolang/parser/parse/build-fqns.xsl | 28 +++++++++++++ .../eolang/parser/parse/resolve-compacts.xsl | 40 ------------------- .../eolang/parser/CompactArrayFqnTest.java | 3 +- .../parse/validate-resolve-before-stars.yaml | 15 ++++--- 6 files changed, 38 insertions(+), 51 deletions(-) delete mode 100644 eo-parser/src/main/resources/org/eolang/parser/parse/resolve-compacts.xsl diff --git a/eo-parser/src/main/java/org/eolang/parser/CompactArrayFqn.java b/eo-parser/src/main/java/org/eolang/parser/CompactArrayFqn.java index 9a8183065c1..19959bcdc53 100644 --- a/eo-parser/src/main/java/org/eolang/parser/CompactArrayFqn.java +++ b/eo-parser/src/main/java/org/eolang/parser/CompactArrayFqn.java @@ -47,7 +47,7 @@ public String asString() { .collect(Collectors.joining(".")); final String fqn; if (this.context.HOME() == null && this.context.XI() == null) { - fqn = String.format("@compact:%s", name); + fqn = name; } else if (this.context.HOME() != null && this.context.XI() == null) { fqn = String.format("Φ.org.eolang.%s", name); } else { diff --git a/eo-parser/src/main/java/org/eolang/parser/EoSyntax.java b/eo-parser/src/main/java/org/eolang/parser/EoSyntax.java index feacab55e41..3d819a42074 100644 --- a/eo-parser/src/main/java/org/eolang/parser/EoSyntax.java +++ b/eo-parser/src/main/java/org/eolang/parser/EoSyntax.java @@ -98,7 +98,6 @@ public final class EoSyntax implements Syntax { "/org/eolang/parser/parse/expand-qqs.xsl", "/org/eolang/parser/parse/expand-aliases.xsl", "/org/eolang/parser/parse/resolve-aliases.xsl", - "/org/eolang/parser/parse/resolve-compacts.xsl", "/org/eolang/parser/parse/add-default-package.xsl", "/org/eolang/parser/parse/roll-bases.xsl", "/org/eolang/parser/parse/cti-adds-errors.xsl", diff --git a/eo-parser/src/main/resources/org/eolang/parser/parse/build-fqns.xsl b/eo-parser/src/main/resources/org/eolang/parser/parse/build-fqns.xsl index 4ca4faceca1..50f6ee52849 100644 --- a/eo-parser/src/main/resources/org/eolang/parser/parse/build-fqns.xsl +++ b/eo-parser/src/main/resources/org/eolang/parser/parse/build-fqns.xsl @@ -185,6 +185,34 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/eo-parser/src/main/resources/org/eolang/parser/parse/resolve-compacts.xsl b/eo-parser/src/main/resources/org/eolang/parser/parse/resolve-compacts.xsl deleted file mode 100644 index b0ea58c940c..00000000000 --- a/eo-parser/src/main/resources/org/eolang/parser/parse/resolve-compacts.xsl +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/eo-parser/src/test/java/org/eolang/parser/CompactArrayFqnTest.java b/eo-parser/src/test/java/org/eolang/parser/CompactArrayFqnTest.java index 1b28e726559..70fad753981 100644 --- a/eo-parser/src/test/java/org/eolang/parser/CompactArrayFqnTest.java +++ b/eo-parser/src/test/java/org/eolang/parser/CompactArrayFqnTest.java @@ -19,7 +19,8 @@ final class CompactArrayFqnTest { @ParameterizedTest @CsvSource( { - "foo *1,@compact:foo", + "foo *1,foo", + "tt.x *55,tt.x", "QQ.foo.bar *42,Φ.org.eolang.foo.bar", "QQ.nan *52,Φ.org.eolang.nan", "$.seq *1,ξ.seq" diff --git a/eo-parser/src/test/resources/org/eolang/parser/eo-packs/parse/validate-resolve-before-stars.yaml b/eo-parser/src/test/resources/org/eolang/parser/eo-packs/parse/validate-resolve-before-stars.yaml index 71d5979a7d0..70d9f631118 100644 --- a/eo-parser/src/test/resources/org/eolang/parser/eo-packs/parse/validate-resolve-before-stars.yaml +++ b/eo-parser/src/test/resources/org/eolang/parser/eo-packs/parse/validate-resolve-before-stars.yaml @@ -3,7 +3,6 @@ --- # yamllint disable rule:line-length sheets: - - /org/eolang/parser/parse/resolve-compacts.xsl - /org/eolang/parser/parse/validate-before-stars.xsl - /org/eolang/parser/parse/resolve-before-stars.xsl asserts: @@ -11,27 +10,27 @@ asserts: - //o[@name='first' and count(o)=1]/o[@base='Φ.org.eolang.tuple' and @star and count(o)=2] - //o[@name='second' and count(o)=2]/o[position()=2 and @base='Φ.org.eolang.tuple' and @star and count(o)=2] - //o[@name='third' and count(o)=3]/o[position()=3 and @base='Φ.org.eolang.tuple' and @star and count(o)=1] - - //o[@name='fourth' and count(o)=2]/o[@base='Φ.org.eolang.sprintf' and count(o)=1]/o[@base='Φ.org.eolang.tuple' and @star and count(o)=2] + - //o[@name='fourth' and count(o)=2]/o[@base='Φ.org.eolang.tt.sprintf' and count(o)=1]/o[@base='Φ.org.eolang.tuple' and @star and count(o)=2] - //o[@name='fourth']/o[@base='Φ.org.eolang.tuple' and @star and count(o)=1] - /object[count(//o[@before-star])=0] input: | # No comments. [] > foo - sprintf *2 > with-error + QQ.tt.sprintf *2 > with-error x - sprintf * > first + QQ.tt.sprintf * > first x y - sprintf *1 > second + QQ.tt.sprintf *1 > second x y z - sprintf *2 > third + QQ.tt.sprintf *2 > third x y z - sprintf *1 > fourth - sprintf * + QQ.tt.sprintf *1 > fourth + QQ.tt.sprintf * x y z