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

bug(#3481): builds FQN via XSL #3808

Merged
merged 3 commits into from
Jan 13, 2025
Merged
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,10 @@ SOFTWARE.
global or just a mistake.

We must not add "ref" attributes to objects that refer to
"bytes" if such objects are inside the "org.eolang.bytes". Such
a reference would be misleading: instead of referring to the
global "org.eolang.bytes" they will lead to local "bytes"
"bytes", "string" or "number" if such objects are inside the
"org.eolang.bytes", "org.eolang.string" or "org.eolang.bytes".
Such a reference would be misleading: instead of referring to the
global, for example, "org.eolang.bytes" they will lead to local "bytes"
defined in this particular file.
-->
<xsl:output encoding="UTF-8" method="xml"/>
Expand Down
181 changes: 181 additions & 0 deletions eo-parser/src/main/resources/org/eolang/parser/shake/build-fqns.xsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
The MIT License (MIT)

Copyright (c) 2016-2025 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="build-fqns" version="2.0">
<!--
Here we go through all objects and find what their @base
are referring to. If we find the object they refer to,
we add either $ object (if target object in the same scope)
or necessary amount of ^. objects. Those objects
which are skipped after this transformation
are not visible in the current scope. Maybe they are
global or just a mistake.

We must skip objects that refer to
"bytes", "string" or "number" if such objects are inside the
"org.eolang.bytes", "org.eolang.string" or "org.eolang.bytes".
Such a reference would be misleading: instead of referring to the
global, for example, "org.eolang.bytes" they will lead to local "bytes"
defined in this particular file.
-->
<xsl:output encoding="UTF-8" method="xml"/>
<xsl:import href="/org/eolang/parser/_funcs.xsl"/>
<xsl:variable name="primitives" as="element()*">
<a>bytes</a>
<a>string</a>
<a>number</a>
</xsl:variable>
<xsl:variable name="this">
<xsl:element name="o">
<xsl:attribute name="base" select="'$'"/>
</xsl:element>
</xsl:variable>
<!-- Convert given object to method -->
<xsl:template match="o" mode="to-method">
<xsl:param name="of"/>
<xsl:element name="o">
<xsl:attribute name="base">
<xsl:text>.</xsl:text>
<xsl:value-of select="@base"/>
</xsl:attribute>
<xsl:apply-templates select="@* except @base"/>
<xsl:copy-of select="$of"/>
<xsl:apply-templates select="o"/>
</xsl:element>
</xsl:template>
<!-- ADD ^. TO GIVEN OBJECT (OR NOT) -->
<xsl:template match="o" mode="with-rho">
<xsl:param name="rhos"/>
<xsl:param name="current"/>
<xsl:choose>
<!-- No need to add rho - we're in the current scope, but in application -->
<xsl:when test="$rhos=0">
<xsl:apply-templates select="." mode="to-method">
<xsl:with-param name="of" select="$this"/>
</xsl:apply-templates>
</xsl:when>
<!-- We're in the end of recursion -->
<xsl:when test="$rhos=1">
<xsl:apply-templates select="." mode="to-method">
<xsl:with-param name="of" select="$current"/>
</xsl:apply-templates>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates mode="with-rho" select=".">
<xsl:with-param name="rhos" select="$rhos - 1"/>
<xsl:with-param name="current">
<xsl:element name="o">
<xsl:attribute name="base" select="'.^'"/>
<xsl:copy-of select="$current"/>
</xsl:element>
</xsl:with-param>
</xsl:apply-templates>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- BUILD FQN PATH TO OBJECT -->
<xsl:template match="o|objects" mode="fqn">
<xsl:param name="rhos"/>
<xsl:param name="self"/>
<xsl:param name="find"/>
<xsl:variable name="parent" select="parent::*"/>
<xsl:choose>
<!-- last frontier -->
<xsl:when test="$parent[name()='objects']">
<xsl:element name="o">
<xsl:apply-templates select="$self/o|$self/@*"/>
</xsl:element>
</xsl:when>
<xsl:when test="eo:abstract($parent)">
<xsl:choose>
<!-- Found reference in some abstract object above -->
<xsl:when test="$parent/o[@name=$find]">
<xsl:apply-templates select="$self" mode="with-rho">
<xsl:with-param name="rhos" select="$rhos"/>
<xsl:with-param name="current">
<xsl:element name="o">
<xsl:attribute name="base" select="'^'"/>
</xsl:element>
</xsl:with-param>
</xsl:apply-templates>
</xsl:when>
<!-- No reference - go upper -->
<xsl:otherwise>
<xsl:apply-templates select="$parent" mode="fqn">
<xsl:with-param name="self" select="$self"/>
<xsl:with-param name="rhos" select="$rhos + 1"/>
<xsl:with-param name="find" select="$find"/>
</xsl:apply-templates>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<!-- Parent is not abstract (application) - try to find reference upper -->
<xsl:otherwise>
<xsl:apply-templates select="$parent" mode="fqn">
<xsl:with-param name="self" select="$self"/>
<xsl:with-param name="find" select="$find"/>
<xsl:with-param name="rhos" select="$rhos"/>
</xsl:apply-templates>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- ENTRY POINT -->
<xsl:template match="o[not($primitives/text()=@base and /program/objects/o/@name=@base and /program/metas/meta[head='package' and tail='org.eolang'])]">
<xsl:apply-templates select="." mode="not-primitive"/>
</xsl:template>
<xsl:template match="o[@base]" mode="not-primitive">
<xsl:apply-templates select="." mode="with-base"/>
</xsl:template>
<xsl:template match="o[not(contains(@base, '.'))]" mode="with-base">
<xsl:apply-templates select="." mode="no-dots"/>
</xsl:template>
<xsl:template match="o[@base!='$' and @base!='^' and @base!='∅']" mode="no-dots">
<xsl:variable name="base" select="./@base"/>
<xsl:choose>
<!-- Closes object in the same scope -->
<xsl:when test="parent::o/o[@name=$base]">
<xsl:apply-templates select="." mode="to-method">
<xsl:with-param name="of" select="$this"/>
</xsl:apply-templates>
</xsl:when>
<!-- Closest object in the same scope, but global -->
<xsl:when test="parent::objects/o[@name=$base]">
<xsl:copy-of select="."/>
</xsl:when>
<!--- Try to find the closest object in parents -->
<xsl:otherwise>
<xsl:apply-templates select="." mode="fqn">
<xsl:with-param name="self" select="."/>
<xsl:with-param name="find" select="$base"/>
<xsl:with-param name="rhos" select="0"/>
</xsl:apply-templates>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="node()|@*" mode="#all">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# The MIT License (MIT)
#
# Copyright (c) 2016-2025 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.
---
sheets:
- /org/eolang/parser/shake/build-fqns.xsl
asserts:
- /program[not(errors)]
- /program/objects[count(o)=3]
- /program/objects/o[@base='foo' and @name='bar']
- /program/objects/o[@name='foo']
- /program/objects/o[@name='first']/o[@base='stdout' and @name='std']/o[@base='.x']/o[@base='$']
- /program/objects/o[@name='first']/o[@name='second']/o[@base='.std']/o[1][@base='$']
- /program/objects/o[@name='first']/o[@name='second']/o[@base='.std']/o[2][@base='.x']/o[1][@base='^']
- /program/objects/o[@name='first']/o[@name='second']/o[@name='third']/o[@base='number' and @name='x']
- /program/objects/o[@name='first']/o[@name='second']/o[@name='third']/o[@base='.plus']/o[1][@base='.x']/o[1][@base='$']
- /program/objects/o[@name='first']/o[@name='second']/o[@name='third']/o[@base='.plus']/o[2][@base='.y']/o[1][@base='.^']/o[1][@base='^']
- /program/objects/o[@name='first']/o[@name='second']/o[@name='third']/o[@base='.std']/o[1][@base='^']
- /program/objects/o[@name='first']/o[@name='second']/o[@name='third']/o[@base='.std']/o[2][@base='qwe']
- /program/objects/o[@name='first']/o[@name='second']/o[@name='fourth']/o[@base='string' and @name='inner']
- /program/objects/o[@name='first']/o[@name='second']/o[@name='fourth']/o[@base='.inner' and @name='outer']/o[1][@base='^']
- /program/objects/o[@name='first']/o[@name='second']/o[@name='fourth']/o[@base='.inner' and @name='self']/o[1][@base='$']
input: |-
# No comments.
[x y] > first
stdout x > std
[std] > second
std x > inner
[] > third
5 > x
x.plus y > sum
std qwe > closest
[] > fourth
"some" > inner
^.inner > outer
inner > self
foo > bar

# Foo.
[] > foo
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# The MIT License (MIT)
#
# Copyright (c) 2016-2025 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.
---
sheets:
- /org/eolang/parser/shake/build-fqns.xsl
asserts:
- /program[not(errors)]
- /program/objects[count(o)=3]
- /program/objects/o[@name='number']/o[@base='number' and @name='self' and text()!='']
- /program/objects/o[@name='bytes']/o[@base='bytes' and @name='self' and text()!='']
- /program/objects/o[@name='string']/o[@base='string' and @name='self' and text()!='']
input: |-
+package org.eolang

# No comments.
[] > number
5 > self

# No comment.
[] > bytes
2A- > self

# No comment.
[] > string
"Hello" > self
Loading