Skip to content
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
2 changes: 2 additions & 0 deletions .github/styles/config/vocabularies/Custom/accept.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,7 @@ inlined
[Ff]orma(e)?
[Tt]ranspile(d|s|r)?
[Uu]noptimizable
[Dd]ataiz(e|es|ed|ation)
[Ss]yscall(s)?
[Cc]yclomatic
[Bb]oolean(s)?
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
* SPDX-FileCopyrightText: Copyright (c) 2016-2026 Objectionary.com
* SPDX-License-Identifier: MIT
-->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:eo="https://www.eolang.org" xmlns:xs="http://www.w3.org/2001/XMLSchema" id="misplaced-dataization" version="2.0">
<xsl:import href="/org/eolang/parser/_funcs.xsl"/>
<xsl:import href="/org/eolang/funcs/lineno.xsl"/>
<xsl:import href="/org/eolang/funcs/escape.xsl"/>
<xsl:import href="/org/eolang/funcs/defect-context.xsl"/>
<xsl:import href="/org/eolang/funcs/test-name.xsl"/>
<xsl:output encoding="UTF-8" method="xml"/>
<!--
The name the formation goes by in the source, or the line it starts at
when the source gives it no name: the parser names an anonymous
formation after its position, with a cactus in the middle.
-->
<xsl:function name="eo:label" as="xs:string">
<xsl:param name="o" as="element()"/>
<xsl:variable name="name" select="($o/@local, $o/@name[not(contains(., '🌵'))])[1]"/>
<xsl:sequence select="if ($name) then eo:escape($name) else concat('the formation at line ', eo:lineno($o/@line))"/>
</xsl:function>
<!--
The cache of a "Φ.dataized" lives in the copy of the formation that
holds it. When the formation is nested and the target is a plain chain
of attribute reads through "ξ.ρ", every copy dataizes the same object of
the enclosing formation again, though the enclosing formation could do
it once for all of them. The parser rolls dispatches on a reference into
its name, so such a chain is always one object without arguments; a
literal or an application never is, and that keeps syscalls out, since
each of them must run on every call. Tests are left alone, because
their copies are not repeated.
-->
<xsl:template match="/">
<defects>
<xsl:for-each select="//o[@base = 'Φ.dataized' and count(o) = 1 and o[empty(o) and (@base = 'ξ.ρ' or starts-with(@base, 'ξ.ρ.'))] and not(ancestor::o[eo:test-name(@name)])]">
<xsl:variable name="formation" select="ancestor::o[eo:abstract(.)][1]"/>
<xsl:variable name="outer" select="$formation/ancestor::o[eo:abstract(.)][1]"/>
<xsl:if test="exists($outer)">
<defect>
<xsl:variable name="line" select="eo:lineno(@line)"/>
<xsl:attribute name="line">
<xsl:value-of select="$line"/>
</xsl:attribute>
<xsl:if test="$line = '0'">
<xsl:attribute name="context">
<xsl:value-of select="eo:defect-context(.)"/>
</xsl:attribute>
</xsl:if>
<xsl:attribute name="severity">warning</xsl:attribute>
<xsl:attribute name="experimental">true</xsl:attribute>
<xsl:text>The dataization in </xsl:text>
<xsl:value-of select="eo:label($formation)"/>
<xsl:text> reads only objects outside of it and runs again in every copy, move it up into </xsl:text>
<xsl:value-of select="eo:label($outer)"/>
</defect>
</xsl:if>
</xsl:for-each>
</defects>
</xsl:template>
</xsl:stylesheet>
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Misplaced dataization

The cache of a `!` lives in the formation that holds it. When a nested
formation dataizes an object of the formation around it, every copy of the
nested formation starts with an empty cache and dataizes the same object
again. A recursive formation makes a new copy on every step, so the
delimiter below is dataized once per step, though it never changes:

```eo
[^ items] > joined
[^ acc tup] >> with-delimiter
if. > @
tup.length.eq 0
acc
^.with-delimiter
concat.
concat. (dataized tup.head) ^.^!
acc
tup.tail
```

The lint warns when two things hold. First, the target of a `!` or of a
`dataized` is a plain chain of attribute reads that goes through `^`.
Second, the formation that holds it sits inside another formation of the
same file. Move the dataization up into the enclosing formation, where it
runs once per call:

```eo
[^ items] > joined
^ >> delimiter!
[^ acc tup] >> with-delimiter
if. > @
tup.length.eq 0
acc
^.with-delimiter
concat.
concat. (dataized tup.head) ^.delimiter
acc
tup.tail
```

The lint stays silent on an application, such as `^.sys.accept >>!` with
its arguments, because a syscall must run on every call, and moving it up
would run it only once. It also stays silent on a global, such as `eol!`,
on a top-level formation, whose enclosing object lives in another file,
and inside a test.
3 changes: 2 additions & 1 deletion src/test/java/matchers/GrammarMatcher.java
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ public boolean matches(final Object obj) {
if (rule instanceof SpellingCheckRule) {
((SpellingCheckRule) rule).addIgnoreTokens(
Arrays.asList(
"decoratee", "eolang", "spdx", "SPDX-compliant", "Unlinting", "cyclomatic"
"dataization", "decoratee", "eolang", "spdx", "SPDX-compliant",
"Unlinting", "cyclomatic"
Comment on lines +56 to +57
)
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# SPDX-FileCopyrightText: Copyright (c) 2016-2026 Objectionary.com
# SPDX-License-Identifier: MIT
---
sheets:
- /org/eolang/lints/design/misplaced-dataization.xsl
defects: 0
input: |
[] > server
[^ scope] > accept
as-number. > client
^.sys.accept >>!
^.sd
^.sockaddr
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# SPDX-FileCopyrightText: Copyright (c) 2016-2026 Objectionary.com
# SPDX-License-Identifier: MIT
---
sheets:
- /org/eolang/lints/design/misplaced-dataization.xsl
defects: 0
input: |
[] > counter
[^ n] > bump
^.n.plus 1 > next!
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# SPDX-FileCopyrightText: Copyright (c) 2016-2026 Objectionary.com
# SPDX-License-Identifier: MIT
---
sheets:
- /org/eolang/lints/design/misplaced-dataization.xsl
defects: 0
input: |
[] > foo
42 > bar

[] +> reads-bar-once
eq. > @
^.bar!
42
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# SPDX-FileCopyrightText: Copyright (c) 2016-2026 Objectionary.com
# SPDX-License-Identifier: MIT
---
sheets:
- /org/eolang/lints/design/misplaced-dataization.xsl
defects: 0
input: |
[^ substring] > contains
^ >> txt!
^.as-bytes >> mine!
txt.eq substring > @
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# SPDX-FileCopyrightText: Copyright (c) 2016-2026 Objectionary.com
# SPDX-License-Identifier: MIT
---
sheets:
- /org/eolang/lints/design/misplaced-dataization.xsl
defects: 0
input: |
[^ items] > joined
^ >> delimiter!
[^ acc tup] >> with-delimiter
if. > @
tup.length.eq 0
acc
^.with-delimiter
concat.
concat. (dataized tup.head) ^.delimiter
acc
tup.tail
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# SPDX-FileCopyrightText: Copyright (c) 2016-2026 Objectionary.com
# SPDX-License-Identifier: MIT
---
sheets:
- /org/eolang/lints/design/misplaced-dataization.xsl
defects: 0
input: |
[] > reader
[^ buffer] >> rec
buffer.concat eol! > @
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# SPDX-FileCopyrightText: Copyright (c) 2016-2026 Objectionary.com
# SPDX-License-Identifier: MIT
---
sheets:
- /org/eolang/lints/design/misplaced-dataization.xsl
defects: 0
input: |
[] > list
[^ head tail] >> walk
head.eq tail.length! > @
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# SPDX-FileCopyrightText: Copyright (c) 2016-2026 Objectionary.com
# SPDX-License-Identifier: MIT
---
# yamllint disable rule:line-length
sheets:
- /org/eolang/lints/design/misplaced-dataization.xsl
asserts:
- /defects[count(defect)=1]/defect[@line='6' and normalize-space()='The dataization in the formation at line 5 reads only objects outside of it and runs again in every copy, move it up into the formation at line 2']
input: |
[] > outer
[^] >>
reduced > @
items
[acc x]
acc.plus ^.weight! > @
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# SPDX-FileCopyrightText: Copyright (c) 2016-2026 Objectionary.com
# SPDX-License-Identifier: MIT
---
# yamllint disable rule:line-length
sheets:
- /org/eolang/lints/design/misplaced-dataization.xsl
asserts:
- /defects[count(defect)=1]/defect[@line='4' and normalize-space()='The dataization in "step" reads only objects outside of it and runs again in every copy, move it up into "box"']
input: |
[] > box
42 > size
[^ i] > step
i.lt (dataized ^.size) > @
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# SPDX-FileCopyrightText: Copyright (c) 2016-2026 Objectionary.com
# SPDX-License-Identifier: MIT
---
# yamllint disable rule:line-length
sheets:
- /org/eolang/lints/design/misplaced-dataization.xsl
asserts:
- /defects[count(defect)=1]/defect[@line='8' and @severity='warning' and normalize-space()='The dataization in "with-delimiter" reads only objects outside of it and runs again in every copy, move it up into "joined"']
input: |
[^ items] > joined
[^ acc tup] >> with-delimiter
if. > @
tup.length.eq 0
acc
^.with-delimiter
concat.
concat. (dataized tup.head) ^.^!
acc
tup.tail
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# SPDX-FileCopyrightText: Copyright (c) 2016-2026 Objectionary.com
# SPDX-License-Identifier: MIT
---
# yamllint disable rule:line-length
sheets:
- /org/eolang/lints/design/misplaced-dataization.xsl
asserts:
- /defects[count(defect)=1]/defect[@line='4' and normalize-space()='The dataization in "rolled" reads only objects outside of it and runs again in every copy, move it up into "digest"']
input: |
[^] > digest
^.as-bytes >> raw!
[^ acc index] >> rolled
index.eq raw.size! > @
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# SPDX-FileCopyrightText: Copyright (c) 2016-2026 Objectionary.com
# SPDX-License-Identifier: MIT
---
# yamllint disable rule:line-length
sheets:
- /org/eolang/lints/design/misplaced-dataization.xsl
asserts:
- /defects/defect[normalize-space()='The dataization in "climb" reads only objects outside of it and runs again in every copy, move it up into "node"']
input: |
[] > tree
[^ left] > node
[^ depth] >> climb
depth.lt ^.^.height! > @
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# SPDX-FileCopyrightText: Copyright (c) 2016-2026 Objectionary.com
# SPDX-License-Identifier: MIT
---
sheets:
- /org/eolang/lints/design/misplaced-dataization.xsl
asserts:
- /defects[count(defect[@context and @line='0'])=1]
xml-reason: "parser always emits @line; unreachable via valid parse"
document: |
<object author="tests">
<o name="box">
<o name="step">
<o base="Φ.dataized" name="φ">
<o as="α0" base="ξ.ρ.size"/>
</o>
</o>
</o>
</object>
Loading