Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(#3343): Allow Partial XMIR Printing #3344

Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions eo-parser/src/main/java/org/eolang/parser/xmir/Xmir.java
Original file line number Diff line number Diff line change
Expand Up @@ -110,4 +110,60 @@ public String toEO() {
.get(0);
}
}

/**
* Simplified xmir that allows printing of small parts EO.
volodya-lombrozo marked this conversation as resolved.
Show resolved Hide resolved
*
* @since 0.40
*/
final class Simplified implements Xmir {

/**
* Train of transformations.
*/
private static final Train<Shift> TRAIN = new TrDefault<>(
new StClasspath("/org/eolang/parser/explicit-data.xsl"),
new StUnhex(),
new StClasspath("/org/eolang/parser/wrap-method-calls.xsl")
);

/**
* Default xmir-to-eo-simplified XSL transformation.
*/
private static final String TO_EO = "/org/eolang/parser/xmir-to-eo-simplified.xsl";

/**
* The XML to transform.
*/
private final XML xml;

/**
* Transformation.
*/
private final String xsl;

/**
* Constructor.
* @param src The source to transform.
*/
public Simplified(final XML src) {
this(src, Xmir.Simplified.TO_EO);
}

/**
* Constructor.
* @param src The source to transform.
* @param classpath Transformation classpath.
*/
public Simplified(final XML src, final String classpath) {
this.xml = src;
this.xsl = classpath;
}

@Override
public String toEO() {
return new Xsline(Simplified.TRAIN.with(new StClasspath(this.xsl)))
.pass(this.xml).xpath("eo/text()").get(0);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:eo="https://www.eolang.org" id="xmir-to-eo-simplified" version="2.0">
<!--
This one maps XMIR to EO original syntax in straight notation.
It's used in Xmir.java class.
-->
<xsl:import href="/org/eolang/parser/_funcs.xsl"/>
<xsl:variable name="eol" select="'&#10;'"/>
<xsl:variable name="comment">
<xsl:text># This is the default 64+ symbols comment in front of named abstract object.</xsl:text>
<xsl:value-of select="$eol"/>
</xsl:variable>
<xsl:output method="text" encoding="UTF-8"/>
<!-- ROOT -->
<xsl:template match="/">
<eo>
<xsl:apply-templates/>
</eo>
</xsl:template>
<!-- PROGRAM -->
<xsl:template match="program">
<xsl:apply-templates select="license"/>
<xsl:apply-templates select="metas[meta]"/>
<xsl:apply-templates select="objects"/>
</xsl:template>
<!-- LICENCE -->
<xsl:template match="license">
<xsl:for-each select="tokenize(., $eol)">
<xsl:text># </xsl:text>
<xsl:value-of select="."/>
<xsl:value-of select="$eol"/>
</xsl:for-each>
<xsl:if test="text()">
<xsl:value-of select="$eol"/>
</xsl:if>
</xsl:template>
<!-- METAS -->
<xsl:template match="metas">
<xsl:apply-templates select="meta"/>
<xsl:value-of select="$eol"/>
</xsl:template>
<!-- META -->
<xsl:template match="meta">
<xsl:text>+</xsl:text>
<xsl:value-of select="head"/>
<xsl:if test="not(empty(tail/text()))">
<xsl:text> </xsl:text>
<xsl:value-of select="tail"/>
</xsl:if>
<xsl:value-of select="$eol"/>
</xsl:template>
<!-- OBJECTS -->
<xsl:template match="objects">
<xsl:apply-templates select="o"/>
</xsl:template>
<!-- OBJECT, NOT FREE ATTRIBUTE -->
<xsl:template match="o[not(eo:attr(.))]">
<xsl:param name="indent" select="''"/>
<xsl:choose>
<!-- METHOD -->
<xsl:when test="starts-with(@base,'.')">
<xsl:apply-templates select="o[position()=1]">
<xsl:with-param name="indent" select="$indent"/>
</xsl:apply-templates>
<xsl:value-of select="$indent"/>
<xsl:apply-templates select="." mode="head">
<xsl:with-param name="indent" select="$indent"/>
</xsl:apply-templates>
<xsl:apply-templates select="." mode="tail"/>
<xsl:value-of select="$eol"/>
<xsl:apply-templates select="o[position()&gt;1 and not(eo:attr(.))]">
<xsl:with-param name="indent" select="concat(' ', $indent)"/>
</xsl:apply-templates>
</xsl:when>
<!-- NOT METHOD -->
<xsl:otherwise>
<!--IF NOT THE FIRST TOP OBJECT -->
<xsl:if test="position()&gt;1 and parent::objects">
<xsl:value-of select="$eol"/>
</xsl:if>
<xsl:value-of select="$indent"/>
<xsl:apply-templates select="." mode="head">
<xsl:with-param name="indent" select="$indent"/>
</xsl:apply-templates>
<xsl:apply-templates select="." mode="tail"/>
<xsl:value-of select="$eol"/>
<xsl:apply-templates select="o[not(eo:attr(.))]">
<xsl:with-param name="indent" select="concat(' ', $indent)"/>
</xsl:apply-templates>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- BASED -->
<xsl:template match="o[not(@data) and @base]" mode="head">
<xsl:choose>
<!-- NOT OPTIMIZED TUPLE -->
<xsl:when test="@star">
<xsl:text>*</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="@base"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- ABSTRACT OR ATOM -->
<xsl:template match="o[not(@data) and not(@base)]" mode="head">
<xsl:param name="indent"/>
<xsl:if test="@name">
<xsl:value-of select="$comment"/>
<xsl:value-of select="$indent"/>
</xsl:if>
<xsl:text>[</xsl:text>
<xsl:for-each select="o[eo:attr(.)]">
<xsl:if test="position()&gt;1">
<xsl:text> </xsl:text>
</xsl:if>
<xsl:value-of select="@name"/>
</xsl:for-each>
<xsl:text>]</xsl:text>
</xsl:template>
<!-- TAIL: SUFFIX, NAME, CONST, ATOM -->
<xsl:template match="o" mode="tail">
<xsl:if test="@as">
<xsl:text>:</xsl:text>
<xsl:value-of select="@as"/>
</xsl:if>
<xsl:if test="@name">
<xsl:text> &gt; </xsl:text>
<xsl:value-of select="@name"/>
<xsl:if test="@const">
<xsl:text>!</xsl:text>
</xsl:if>
<xsl:if test="@atom">
<xsl:text> /</xsl:text>
<xsl:value-of select="@atom"/>
</xsl:if>
</xsl:if>
</xsl:template>
<!-- DATA -->
<xsl:template match="o[@data]" mode="head">
<xsl:choose>
<xsl:when test="@data='string'">
<xsl:text>"</xsl:text>
<xsl:value-of select="text()"/>
<xsl:text>"</xsl:text>
</xsl:when>
<xsl:when test="@data='number'">
<xsl:value-of select="text()"/>
</xsl:when>
<xsl:when test="@data='bytes'">
<xsl:choose>
<xsl:when test="empty(text())">
<xsl:text>--</xsl:text>
</xsl:when>
<xsl:when test="string-length(text())=2">
<xsl:value-of select="text()"/>
<xsl:text>-</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="replace(text(), ' ', '-')"/>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
<xsl:message terminate="yes">
<xsl:text>Invalid data attribute: </xsl:text>
<xsl:value-of select="@data"/>
</xsl:message>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
52 changes: 52 additions & 0 deletions eo-parser/src/test/java/org/eolang/parser/xmir/XmirTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import com.jcabi.log.Logger;
import com.jcabi.matchers.XhtmlMatchers;
import com.jcabi.xml.XML;
import com.jcabi.xml.XMLDocument;
import java.io.IOException;
import java.util.Map;
import java.util.function.Function;
Expand All @@ -34,6 +35,8 @@
import org.eolang.parser.EoSyntax;
import org.hamcrest.MatcherAssert;
import org.hamcrest.Matchers;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.yaml.snakeyaml.Yaml;

Expand Down Expand Up @@ -86,6 +89,55 @@ void printsReversed(final String pack) throws IOException {
);
}

@Test
void failsToPrintPartialXmirWithDefault() {
Assertions.assertThrows(
IllegalArgumentException.class,
() -> new Xmir.Default(
new XMLDocument(
String.join(
"\n",
" <o base='.minus'>",
" <o base='int' data='bytes' >00 00 00 00 00 00 00 03</o>",
" <o base='int' data='bytes' >00 00 00 00 00 00 00 04</o>",
" </o>"
)
)
).toEO(),
String.format("Should fail to print partial XMIR with %s", Xmir.Default.class)
);
}

@Test
void printsPartialXmirWithSimplified() {
MatcherAssert.assertThat(
String.format(
"We expect that %s will print the partial XMIR correctly", Xmir.Simplified.class
),
new Xmir.Simplified(
new XMLDocument(
String.join(
"\n",
" <o base='.plus'>",
" <o base='int' data='bytes'>00 00 00 00 00 00 00 01</o>",
" <o base='int' data='bytes'>00 00 00 00 00 00 00 02</o>",
" </o>"
)
)
).toEO(),
Matchers.equalTo(
String.join(
"\n",
"int",
" 00-00-00-00-00-00-00-01",
".plus",
" int",
" 00-00-00-00-00-00-00-02\n"
)
)
);
}

/**
* Parse EO from given pack, converts XMIR to EO.
* @param original Original EOLANG
Expand Down
Loading