Skip to content

Commit 9c8773c

Browse files
committed
bug(#3864): finished
1 parent 735c4fa commit 9c8773c

10 files changed

Lines changed: 296 additions & 25 deletions

File tree

.github/workflows/integration.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,4 @@ jobs:
4444
key: ubuntu-surefire-jdk-21-maven-${{ hashFiles('**/pom.xml') }}
4545
restore-keys: ubuntu-surefire-jdk-21-maven-
4646
- run: |
47-
mvn clean install -PskipUTs --errors --batch-mode
47+
mvn clean install -Deo:skipLinting -PskipUTs --errors --batch-mode

.github/workflows/mvn.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,4 +56,4 @@ jobs:
5656
- uses: JesseTG/rm@v1.0.3
5757
with:
5858
path: ~/.m2/repository/org/eolang
59-
- run: mvn clean install -PskipITs --errors --batch-mode
59+
- run: mvn clean install -Deo:skipLinting -PskipITs --errors --batch-mode

eo-maven-plugin/src/main/java/org/eolang/maven/LintMojo.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,29 @@ public final class LintMojo extends SafeMojo {
9090
@Parameter(property = "eo.lintAsPackage", required = true, defaultValue = "true")
9191
private boolean lintAsPackage;
9292

93+
/**
94+
* Whether we should skip linting at all.
95+
*
96+
* @checkstyle MemberNameCheck (11 lines)
97+
*/
98+
@SuppressWarnings("PMD.ImmutableField")
99+
@Parameter(property = "eo.skipLinting", required = true, defaultValue = "false")
100+
private boolean skipLinting;
101+
93102
@Override
94103
void exec() throws IOException {
104+
if (this.skipLinting) {
105+
Logger.info(this, "Linting is skipped because eo:skipLinting is TRUE");
106+
} else {
107+
this.lint();
108+
}
109+
}
110+
111+
/**
112+
* Lint.
113+
* @throws IOException If fails
114+
*/
115+
private void lint() throws IOException {
95116
final long start = System.currentTimeMillis();
96117
final Collection<ForeignTojo> tojos = this.scopedTojos().withShaken();
97118
final ConcurrentHashMap<Severity, Integer> counts = new ConcurrentHashMap<>();

eo-parser/src/main/java/org/eolang/parser/Xmir.java

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import com.yegor256.xsline.StEndless;
3232
import com.yegor256.xsline.TrClasspath;
3333
import com.yegor256.xsline.TrDefault;
34+
import com.yegor256.xsline.TrJoined;
3435
import com.yegor256.xsline.Train;
3536
import com.yegor256.xsline.Xsline;
3637
import java.util.Collection;
@@ -61,14 +62,18 @@ public final class Xmir implements XML {
6162
* Train of transformations that prepare XMIR for conversion to EO.
6263
*/
6364
private static final Train<Shift> FOR_EO = new TrFull(
64-
new TrDefault<>(
65-
new StEndless(
66-
new StClasspath("/org/eolang/parser/print/tuples-to-stars.xsl")
65+
new TrJoined<>(
66+
new TrDefault<>(
67+
new StEndless(
68+
new StClasspath("/org/eolang/parser/print/tuples-to-stars.xsl")
69+
)
6770
),
68-
new StClasspath("/org/eolang/parser/print/dataized-to-const.xsl"),
69-
new StClasspath("/org/eolang/parser/print/unhex-data.xsl"),
70-
new StClasspath("/org/eolang/parser/print/wrap-data.xsl"),
71-
new StClasspath("/org/eolang/parser/print/to-eo.xsl")
71+
new TrClasspath<>(
72+
"/org/eolang/parser/print/dataized-to-const.xsl",
73+
"/org/eolang/parser/print/unhex-data.xsl",
74+
"/org/eolang/parser/print/wrap-data.xsl",
75+
"/org/eolang/parser/print/to-eo.xsl"
76+
).back()
7277
)
7378
);
7479

eo-parser/src/main/resources/org/eolang/parser/_funcs.xsl

Lines changed: 91 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -35,31 +35,57 @@ SOFTWARE.
3535
<xsl:param name="o" as="element()"/>
3636
<xsl:sequence select="$o/@base='∅'"/>
3737
</xsl:function>
38-
<xsl:function name="eo:hex-to-utf8" as="xs:string">
39-
<xsl:param name="hex" as="xs:string"/>
40-
<xsl:variable name="hex-upper" select="upper-case(normalize-space($hex))"/>
41-
<xsl:variable name="length" select="string-length($hex-upper)"/>
42-
<xsl:variable name="hex-digits" select="string-to-codepoints('0123456789ABCDEF')"/>
43-
<xsl:variable name="decimal" select="sum(for $i in 1 to $length return (index-of($hex-digits, string-to-codepoints(substring($hex-upper, $i, 1))) - 1) * math:pow(16, $length - $i))"/>
44-
<xsl:value-of select="codepoints-to-string(xs:int($decimal))"/>
45-
</xsl:function>
38+
<!-- BYTES TO STRING -->
4639
<xsl:function name="eo:bytes-to-string" as="xs:string">
4740
<xsl:param name="bytes" as="xs:string"/>
4841
<xsl:choose>
4942
<xsl:when test="$bytes = '--'">
5043
<xsl:sequence select="''"/>
5144
</xsl:when>
5245
<xsl:otherwise>
53-
<xsl:variable name="byte-values" select="for $byte in tokenize($bytes, '-') return eo:hex-to-utf8($byte)"/>
54-
55-
56-
<xsl:sequence select="string-join(for $byte in tokenize($bytes, '-') return eo:hex-to-utf8($byte), '')"/>
46+
<xsl:variable name="decoded">
47+
<xsl:for-each select="eo:decode-bytes(for $byte in (if (ends-with($bytes, '-')) then substring-before($bytes, '-') else tokenize($bytes, '-')) return eo:hex-to-utf8($byte))">
48+
<xsl:choose>
49+
<xsl:when test=".=10">
50+
<xsl:value-of select="'\n'"/>
51+
</xsl:when>
52+
<xsl:when test=".=9">
53+
<xsl:value-of select="'\t'"/>
54+
</xsl:when>
55+
<xsl:when test=".=13">
56+
<xsl:value-of select="'\r'"/>
57+
</xsl:when>
58+
<!-- Keep ASCII characters -->
59+
<xsl:when test=". ge 32 and . le 126">
60+
<xsl:variable name="char" select="codepoints-to-string(.)"/>
61+
<xsl:if test="$char='\' or $char='&quot;'">
62+
<xsl:text>\</xsl:text>
63+
</xsl:if>
64+
<xsl:value-of select="$char"/>
65+
</xsl:when>
66+
<!-- Convert non-ASCII to \uXXXX -->
67+
<xsl:when test=". le 65535">
68+
<xsl:value-of select="concat('\u', eo:int-to-hex(xs:int(.)))"/>
69+
</xsl:when>
70+
<!-- Handle surrogate pairs for code points above U+FFFF -->
71+
<xsl:otherwise>
72+
<!-- 55296 = 0xD800 -->
73+
<xsl:variable name="cp1" select="xs:int(floor((. - 65536) div 1024) + 55296)"/>
74+
<!-- 56320 = 0xDC00 -->
75+
<xsl:variable name="cp2" select="xs:int(((. - 65536) mod 1024) + 56320)"/>
76+
<xsl:value-of select="concat('\u', eo:int-to-hex($cp1), '\u', eo:int-to-hex($cp2))"/>
77+
</xsl:otherwise>
78+
</xsl:choose>
79+
</xsl:for-each>
80+
</xsl:variable>
81+
<xsl:sequence select="$decoded"/>
5782
</xsl:otherwise>
5883
</xsl:choose>
5984
</xsl:function>
60-
<!-- Convert string bytes sequence to double number, e.g. 40-14-00-00-00-00-00-00 => 5 -->
85+
<!-- BYTES TO NUMBER, e.g. 40-14-00-00-00-00-00-00 => 5 -->
6186
<xsl:function name="eo:bytes-to-number" as="xs:anyAtomicType">
6287
<xsl:param name="bytes"/>
88+
<!-- Undash -->
6389
<xsl:variable name="hex" select="translate($bytes, '-', '')"/>
6490
<xsl:variable name="map" as="element()*">
6591
<entry h="0" b="0000"/>
@@ -80,13 +106,64 @@ SOFTWARE.
80106
<entry h="F" b="1111"/>
81107
</xsl:variable>
82108
<xsl:variable name="bin" as="xs:string" select="string-join(for $c in string-to-codepoints(upper-case($hex)) return $map[@h = codepoints-to-string($c)]/@b, '')"/>
109+
<!-- Sign bit (1 for negative, 0 for positive) -->
83110
<xsl:variable name="sign" select="if (substring($bin, 1, 1) = '1') then -1 else 1"/>
111+
<!-- Extract exponent (11 bits) and convert to integer -->
84112
<xsl:variable name="exponentBits" select="substring($bin, 2, 11)"/>
85113
<xsl:variable name="exponent" select="sum(for $i in 1 to string-length($exponentBits) return xs:double(substring($exponentBits, $i, 1)) * math:pow(2, string-length($exponentBits) - $i)) - 1023"/>
114+
<!-- Extract mantissa (52 bits) -->
86115
<xsl:variable name="mantissaBits" select="substring($bin, 13, 52)"/>
87116
<xsl:variable name="mantissaValue">
88-
<xsl:sequence select="sum(for $i in 1 to string-length($mantissaBits) return xs:double(substring($mantissaBits, $i, 1)) * math:pow(2, -$i))"/>
117+
<xsl:sequence select="sum(for $i in 1 to string-length($mantissaBits) return xs:double(substring($mantissaBits, $i, 1)) div math:pow(2, $i))"/>
89118
</xsl:variable>
119+
<!-- Compute final double value -->
90120
<xsl:sequence select="$sign * (1 + $mantissaValue) * math:pow(2, $exponent)"/>
91121
</xsl:function>
122+
<!-- HELPER FUNCTIONS -->
123+
<!-- Function to decode UTF-8 bytes into Unicode code points -->
124+
<xsl:function name="eo:decode-bytes" as="xs:integer*">
125+
<xsl:param name="bytes" as="xs:integer*"/>
126+
<xsl:choose>
127+
<!-- 1-byte sequence: 0xxxxxxx -->
128+
<xsl:when test="$bytes[1] lt 128">
129+
<xsl:sequence select="$bytes[1]"/>
130+
<xsl:sequence select="eo:decode-bytes(subsequence($bytes, 2))"/>
131+
</xsl:when>
132+
<!-- 2-byte sequence: 110xxxxx 10xxxxxx -->
133+
<xsl:when test="$bytes[1] ge 192 and $bytes[1] lt 224">
134+
<xsl:variable name="code-point" select="(($bytes[1] - 192) * 64) + ($bytes[2] - 128)"/>
135+
<xsl:sequence select="$code-point"/>
136+
<xsl:sequence select="eo:decode-bytes(subsequence($bytes, 3))"/>
137+
</xsl:when>
138+
<!-- 3-byte sequence: 1110xxxx 10xxxxxx 10xxxxxx -->
139+
<xsl:when test="$bytes[1] ge 224 and $bytes[1] lt 240">
140+
<xsl:variable name="code-point" select="(($bytes[1] - 224) * 4096) + (($bytes[2] - 128) * 64) + ($bytes[3] - 128)"/>
141+
<xsl:sequence select="$code-point"/>
142+
<xsl:sequence select="eo:decode-bytes(subsequence($bytes, 4))"/>
143+
</xsl:when>
144+
<!-- 4-byte sequence: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx -->
145+
<xsl:when test="$bytes[1] ge 240 and $bytes[1] lt 248">
146+
<xsl:variable name="code-point" select="(($bytes[1] - 240) * 262144) + (($bytes[2] - 128) * 4096) + (($bytes[3] - 128) * 64) + ($bytes[4] - 128)"/>
147+
<xsl:sequence select="$code-point"/>
148+
<xsl:sequence select="eo:decode-bytes(subsequence($bytes, 5))"/>
149+
</xsl:when>
150+
<!-- Otherwise, return empty (should not occur if input is valid UTF-8) -->
151+
<xsl:otherwise/>
152+
</xsl:choose>
153+
</xsl:function>
154+
<!-- Function to convert integer to 4-digit hex string -->
155+
<xsl:function name="eo:int-to-hex" as="xs:string">
156+
<xsl:param name="value" as="xs:integer"/>
157+
<xsl:variable name="hex-chars" select="'0123456789ABCDEF'"/>
158+
<xsl:variable name="hex" select="concat(substring($hex-chars, floor($value idiv 4096) + 1, 1), substring($hex-chars, floor(($value mod 4096) idiv 256) + 1, 1), substring($hex-chars, floor(($value mod 256) idiv 16) + 1, 1), substring($hex-chars, ($value mod 16) + 1, 1))"/>
159+
<xsl:sequence select="$hex"/>
160+
</xsl:function>
161+
<xsl:function name="eo:hex-to-utf8" as="xs:integer">
162+
<xsl:param name="hex" as="xs:string"/>
163+
<xsl:variable name="hex-upper" select="upper-case(normalize-space($hex))"/>
164+
<xsl:variable name="length" select="string-length($hex-upper)"/>
165+
<xsl:variable name="hex-digits" select="string-to-codepoints('0123456789ABCDEF')"/>
166+
<xsl:variable name="decimal" select="sum(for $i in 1 to $length return (index-of($hex-digits, string-to-codepoints(substring($hex-upper, $i, 1))) - 1) * math:pow(16, $length - $i))"/>
167+
<xsl:value-of select="xs:int($decimal)"/>
168+
</xsl:function>
92169
</xsl:stylesheet>

eo-parser/src/main/resources/org/eolang/parser/print/unhex-data.xsl

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ SOFTWARE.
3838
</xsl:template>
3939
<xsl:template match="o[@base='Q.org.eolang.number' and o[1][eo:has-data(.)]]">
4040
<xsl:variable name="bytes" select="o[1]/text()"/>
41-
<xsl:variable name="num" select="eo:bytes-to-number($bytes)"/>
4241
<xsl:choose>
4342
<xsl:when test="$bytes='7F-F8-00-00-00-00-00-00' or $bytes='7F-F0-00-00-00-00-00-00' or $bytes='FF-F0-00-00-00-00-00-00'">
4443
<xsl:copy-of select="."/>
@@ -58,7 +57,7 @@ SOFTWARE.
5857
<xsl:otherwise>
5958
<xsl:copy>
6059
<xsl:apply-templates select="@*"/>
61-
<xsl:value-of select="$num"/>
60+
<xsl:value-of select="eo:bytes-to-number($bytes)"/>
6261
</xsl:copy>
6362
</xsl:otherwise>
6463
</xsl:choose>
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# The MIT License (MIT)
2+
#
3+
# Copyright (c) 2016-2025 Objectionary.com
4+
#
5+
# Permission is hereby granted, free of charge, to any person obtaining a copy
6+
# of this software and associated documentation files (the "Software"), to deal
7+
# in the Software without restriction, including without limitation the rights
8+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
# copies of the Software, and to permit persons to whom the Software is
10+
# furnished to do so, subject to the following conditions:
11+
#
12+
# The above copyright notice and this permission notice shall be included
13+
# in all copies or substantial portions of the Software.
14+
#
15+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
18+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
# SOFTWARE.
22+
---
23+
input: |
24+
# No comments.
25+
[] > main
26+
regex "/^[\\x00-\\x7F]*$/" > rgx
27+
"foo\\bar<:>?*\"|baz\\asdf" > ptn
28+
sweet: |-
29+
{⟦
30+
main ↦ ⟦
31+
rgx ↦ Φ̇.regex("/^[\\x00-\\x7F]*$/"),
32+
ptn ↦ "foo\\bar<:>?*\"|baz\\asdf"
33+
34+
⟧}
35+
salty: |-
36+
{
37+
38+
main ↦ ⟦
39+
rgx ↦ Φ.org.eolang.regex(
40+
α0 ↦ Φ.org.eolang.string(
41+
α0 ↦ Φ.org.eolang.bytes(
42+
α0 ↦ ⟦ Δ ⤍ 2F-5E-5B-5C-78-30-30-2D-5C-78-37-46-5D-2A-24-2F ⟧
43+
)
44+
)
45+
),
46+
ptn ↦ Φ.org.eolang.string(
47+
α0 ↦ Φ.org.eolang.bytes(
48+
α0 ↦ ⟦ Δ ⤍ 66-6F-6F-5C-62-61-72-3C-3A-3E-3F-2A-22-7C-62-61-7A-5C-61-73-64-66 ⟧
49+
)
50+
)
51+
52+
53+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# The MIT License (MIT)
2+
#
3+
# Copyright (c) 2016-2025 Objectionary.com
4+
#
5+
# Permission is hereby granted, free of charge, to any person obtaining a copy
6+
# of this software and associated documentation files (the "Software"), to deal
7+
# in the Software without restriction, including without limitation the rights
8+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
# copies of the Software, and to permit persons to whom the Software is
10+
# furnished to do so, subject to the following conditions:
11+
#
12+
# The above copyright notice and this permission notice shall be included
13+
# in all copies or substantial portions of the Software.
14+
#
15+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
18+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
# SOFTWARE.
22+
---
23+
input: |
24+
# No comments.
25+
[] > main
26+
"🌵" > cactoos
27+
"😀" > smile
28+
sweet: |-
29+
{⟦
30+
main ↦ ⟦
31+
cactoos ↦ "\uD83C\uDF35",
32+
smile ↦ "\uD83D\uDE00"
33+
34+
⟧}
35+
salty: |-
36+
{
37+
38+
main ↦ ⟦
39+
cactoos ↦ Φ.org.eolang.string(
40+
α0 ↦ Φ.org.eolang.bytes(
41+
α0 ↦ ⟦ Δ ⤍ F0-9F-8C-B5 ⟧
42+
)
43+
),
44+
smile ↦ Φ.org.eolang.string(
45+
α0 ↦ Φ.org.eolang.bytes(
46+
α0 ↦ ⟦ Δ ⤍ F0-9F-98-80 ⟧
47+
)
48+
)
49+
50+
51+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# The MIT License (MIT)
2+
#
3+
# Copyright (c) 2016-2025 Objectionary.com
4+
#
5+
# Permission is hereby granted, free of charge, to any person obtaining a copy
6+
# of this software and associated documentation files (the "Software"), to deal
7+
# in the Software without restriction, including without limitation the rights
8+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
# copies of the Software, and to permit persons to whom the Software is
10+
# furnished to do so, subject to the following conditions:
11+
#
12+
# The above copyright notice and this permission notice shall be included
13+
# in all copies or substantial portions of the Software.
14+
#
15+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
18+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
# SOFTWARE.
22+
---
23+
origin: |
24+
# No comments.
25+
[] > main
26+
regex "/^[\\x00-\\x7F]*$/" > rgx
27+
28+
printed: |
29+
# No comments.
30+
[] > main
31+
regex > rgx
32+
"/^[\\x00-\\x7F]*$/"

0 commit comments

Comments
 (0)