diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..fb209a2
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+*aoi_l
+.idea
+proloog.pl
\ No newline at end of file
diff --git a/aoi-l.iml b/aoi-l.iml
new file mode 100644
index 0000000..cc81296
--- /dev/null
+++ b/aoi-l.iml
@@ -0,0 +1,75 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..1b63d73
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,125 @@
+
+
+ 4.0.0
+
+ com.jcabi
+ parent
+ 0.63.2
+
+
+ aoi-l
+ org.example
+ 1.0-SNAPSHOT
+ jar
+
+ consoleApp
+
+
+ UTF-8
+ official
+ 1.8
+
+
+
+
+ mavenCentral
+ https://repo1.maven.org/maven2/
+
+
+
+
+ src/main/kotlin
+ src/test/kotlin
+
+
+ org.jetbrains.kotlin
+ kotlin-maven-plugin
+ 1.7.10
+
+
+ compile
+ compile
+
+ compile
+
+
+
+ test-compile
+ test-compile
+
+ test-compile
+
+
+
+
+
+ maven-surefire-plugin
+ 2.22.2
+
+
+ maven-failsafe-plugin
+ 2.22.2
+
+
+ org.codehaus.mojo
+ exec-maven-plugin
+ 1.6.0
+
+ MainKt
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+ 8
+
+
+
+
+
+
+
+ org.eolang
+ eo-parser
+ 0.28.10
+
+
+ org.eolang
+ deog
+ 0.0.4
+
+
+ com.jcabi
+ jcabi-xml
+ 0.25.5
+
+
+ org.slf4j
+ *
+
+
+
+
+ org.jetbrains.kotlin
+ kotlin-test-junit5
+ 1.7.10
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter-engine
+ 5.8.2
+ test
+
+
+ org.jetbrains.kotlin
+ kotlin-stdlib-jdk8
+ 1.7.10
+
+
+
+
\ No newline at end of file
diff --git a/src/main/kotlin/org/objectionary/aoi/generate/PlGenerator.kt b/src/main/kotlin/org/objectionary/aoi/generate/PlGenerator.kt
new file mode 100644
index 0000000..b987c3e
--- /dev/null
+++ b/src/main/kotlin/org/objectionary/aoi/generate/PlGenerator.kt
@@ -0,0 +1,110 @@
+package org.objectionary.aoi.generate
+
+import org.objectionary.aoi.generate.util.*
+import org.objectionary.aoi.sources.SourcesExtractor
+import org.objectionary.deog.abstract
+import org.objectionary.deog.base
+import org.objectionary.deog.name
+import org.objectionary.deog.packageName
+import org.w3c.dom.Document
+import org.w3c.dom.Node
+import java.io.File
+import java.io.Serializable
+
+typealias GraphAbstracts = MutableMap>
+
+class PlGenerator {
+ fun generatePrologScripts(path: String) {
+ File("proloog.pl").createNewFile()
+ val sourcesExtractor = SourcesExtractor()
+ val documents = sourcesExtractor.collectDocuments(path)
+ documents.forEach {
+ generatePrologScript(it.key)
+ }
+ rules()
+ }
+
+ private fun generatePrologScript(document: Document) {
+ val objects: MutableList = mutableListOf()
+ val docObjects = document.getElementsByTagName("o")
+ val packageName = packageName(docObjects.item(0))
+ for (i in 0 until docObjects.length) {
+ objects.add(docObjects.item(i))
+ }
+ val obj = document.getElementsByTagName("objects").item(0)
+ val children = obj.childNodes ?: return
+ for (i in 0 until children.length) {
+ val node = children.item(i)
+ abstract(node)?.let {
+ collectNodeInfo(node)
+ }
+ }
+ }
+
+ private fun collectNodeInfo(node: Node) {
+ val children = node.childNodes ?: return
+ var offset = 0
+ for (i in 0 until children.length) {
+ if (i + offset >= children.length) break
+ val child = children.item(i + offset)
+ abstract(child)?.let {
+ containsAttrFact(name(node)!!, name(child)!!)
+ }
+ base(child)?.let {
+ if (!it.startsWith(".")) {
+ val (txt, j, name) = walkDotChain(child)
+ name?.let {n ->
+ if (n == "@") {
+ parentFact(txt, getFqn(name(node)!!, node.parentNode))
+ } else {
+ isInstanceFact(n, getFqn(name(node)!!, node.parentNode))
+ }
+ }
+ offset += j
+ }
+ }
+ collectNodeInfo(child)
+ }
+ }
+
+ /**
+ * @return concatenated test of bases, nu,ber of passed children, true if name == "@" else false
+ */
+ private fun walkDotChain(
+ node: Node
+ ): Triple {
+ var txt = base(node)
+ var i = 0
+ var sibling = node.nextSibling?.nextSibling
+ while (base(sibling)?.startsWith(".") == true) {
+ txt += base(sibling)
+ i++
+ var tmp = sibling?.nextSibling
+ tmp?.attributes ?: run { tmp = tmp?.nextSibling }
+ if (base(tmp)?.startsWith('.') == true) sibling = tmp
+ else break
+ }
+ return Triple(txt!!, i, name(sibling))
+ }
+
+ private fun getFqn(name: String, par: Node): String {
+ var fqn = name
+ var parent = par
+ while (name(parent) != null) {
+ fqn = "${name(parent)}.$fqn"
+ parent = parent.parentNode
+ }
+ return fqn
+ }
+
+ @Suppress("PARAMETER_NAME_IN_OUTER_LAMBDA")
+ private fun abstracts(objects: MutableList) {
+ val abstracts: GraphAbstracts = mutableMapOf()
+ objects.forEach {
+ val name = name(it)
+ if (abstract(it) != null && name != null) {
+ abstracts.getOrPut(name) { mutableSetOf() }.add(it)
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/org/objectionary/aoi/generate/util/FileWriter.kt b/src/main/kotlin/org/objectionary/aoi/generate/util/FileWriter.kt
new file mode 100644
index 0000000..e9d6388
--- /dev/null
+++ b/src/main/kotlin/org/objectionary/aoi/generate/util/FileWriter.kt
@@ -0,0 +1,28 @@
+package org.objectionary.aoi.generate.util
+
+import java.io.File
+
+val plFile = File("proloog.pl").outputStream()
+
+fun containsAttrFact(nodeName: String, childName: String) {
+ plFile.write("contains_attr($nodeName, $childName, fact).\n".toByteArray())
+}
+
+fun parentFact(nodeName: String, childName: String) {
+ plFile.write("parent($nodeName, $childName, fact).\n".toByteArray())
+}
+
+fun isInstanceFact(nodeName: String, childName: String) {
+ plFile.write("is_instance($nodeName, $childName, fact).\n".toByteArray())
+}
+
+fun rules() {
+ val rules = "\n% rules\n" +
+ "contains_attr(X, Y, rule) :- parent(Z, X, _),\n" +
+ " contains_attr(Z, Y, _).\n" +
+ "contains_attr(X, Y, rule) :- is_instance(X, Z, fact),\n" +
+ " contains_attr(Z, Y, _).\n" +
+ "parent(X, Y, rule) :- parent(X, Z, fact), parent(Z, Y, fact)."
+
+ plFile.write(rules.toByteArray())
+}
diff --git a/src/main/kotlin/org/objectionary/aoi/launch/AoiLauncher.kt b/src/main/kotlin/org/objectionary/aoi/launch/AoiLauncher.kt
new file mode 100644
index 0000000..2f14311
--- /dev/null
+++ b/src/main/kotlin/org/objectionary/aoi/launch/AoiLauncher.kt
@@ -0,0 +1,7 @@
+package org.objectionary.aoi.launch
+
+import org.objectionary.aoi.generate.PlGenerator
+
+fun main(args: Array) {
+ PlGenerator().generatePrologScripts("C:\\Users\\lesya\\aoi-l\\src\\test\\resources\\unit\\in\\inner_usages\\basic")
+}
\ No newline at end of file
diff --git a/src/main/kotlin/org/objectionary/aoi/sources/SourcesExtractor.kt b/src/main/kotlin/org/objectionary/aoi/sources/SourcesExtractor.kt
new file mode 100644
index 0000000..8f39b1f
--- /dev/null
+++ b/src/main/kotlin/org/objectionary/aoi/sources/SourcesExtractor.kt
@@ -0,0 +1,88 @@
+package org.objectionary.aoi.sources
+
+import com.jcabi.xml.XML
+import com.jcabi.xml.XMLDocument
+import com.yegor256.xsline.TrClasspath
+import com.yegor256.xsline.Xsline
+import org.eolang.parser.ParsingTrain
+import org.slf4j.LoggerFactory
+import org.w3c.dom.Document
+import java.io.File
+import java.io.FileInputStream
+import java.nio.file.Files
+import java.nio.file.Paths
+import javax.xml.parsers.DocumentBuilderFactory
+
+class SourcesExtractor {
+
+ private val logger = LoggerFactory.getLogger("org.objectionary.deog.launch.DeogLauncher")
+ private val sep = File.separatorChar
+
+ fun collectDocuments(path: String): MutableMap {
+ val documents: MutableMap = mutableMapOf()
+ Files.walk(Paths.get(path))
+ .filter(Files::isRegularFile)
+ .forEach {
+ val tmpPath = createTempDirectories(path, it.toString())
+ transformXml(it.toString(), tmpPath)
+ documents[getDocument(tmpPath)!!] = tmpPath
+ }
+ return documents
+ }
+
+ /**
+ * Creates a new xml by applying several xsl transformations to it
+ *
+ * @param inFilename to the input file
+ * @param outFilename path to the output file
+ */
+ private fun transformXml(
+ inFilename: String,
+ outFilename: String
+ ) {
+ val xmir: XML = XMLDocument(File(inFilename))
+ val after = Xsline(
+ TrClasspath(
+ ParsingTrain().empty(),
+ "/org/eolang/parser/add-refs.xsl",
+ "/org/eolang/parser/expand-aliases.xsl",
+ "/org/eolang/parser/resolve-aliases.xsl",
+ "/org/eolang/parser/add-default-package.xsl"
+ // "/org/eolang/parser/wrap-method-calls.xsl"
+ ).back()
+ ).pass(xmir)
+ File(outFilename).outputStream().write(after.toString().toByteArray())
+ }
+
+ /**
+ * @param filename source xml filename
+ * @return generated Document
+ */
+ private fun getDocument(filename: String): Document? {
+ try {
+ val factory = DocumentBuilderFactory.newInstance()
+ FileInputStream(filename).use { return factory.newDocumentBuilder().parse(it) }
+ } catch (e: Exception) {
+ logger.error(e.printStackTrace().toString())
+ }
+ return null
+ }
+
+ private fun createTempDirectories(
+ path: String,
+ filename: String
+ ): String {
+ val tmpPath =
+ "${path.substringBeforeLast(sep)}$sep${path.substringAfterLast(sep)}_aoi_l${filename.substring(path.length)}"
+
+ val forDirs = File(tmpPath.substringBeforeLast(sep)).toPath()
+ Files.createDirectories(forDirs)
+ val newFilePath = Paths.get(tmpPath)
+ try {
+ Files.createFile(newFilePath)
+ } catch (e: Exception) {
+ logger.error(e.message)
+ }
+ return tmpPath
+ }
+}
\ No newline at end of file
diff --git a/src/test/resources/unit/app.xmir b/src/test/resources/unit/app.xmir
new file mode 100644
index 0000000..52aea0f
--- /dev/null
+++ b/src/test/resources/unit/app.xmir
@@ -0,0 +1,92 @@
+
+
+ [] > animal
+ [] > talk
+
+[] > cat
+ animal > @
+ [] > talk
+ QQ.io.stdout > @
+ "Meow!"
+ [dir] > move
+ QQ.io.stdout > @
+ dir
+ [] > smth
+
+[] > dog
+ animal > @
+ [dir] > move
+ QQ.io.stdout > @
+ dir
+ [] > smth
+ cat.move > @
+
+[x] > some_object
+ x.talk > t
+ x.move "left" > @
+
+[] > app
+ some_object dog > so
+ so > @
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Meow!
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ left
+
+
+
+
+
+
+
+
+
+
diff --git a/src/test/resources/unit/in/atoms/bool/bool.xmir b/src/test/resources/unit/in/atoms/bool/bool.xmir
new file mode 100644
index 0000000..0530c9d
--- /dev/null
+++ b/src/test/resources/unit/in/atoms/bool/bool.xmir
@@ -0,0 +1,180 @@
+
+
+ # The MIT License (MIT)
+#
+# Copyright (c) 2016-2022 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.
+
++architect yegor256@gmail.com
++home https://github.com/objectionary/eo
++package org.eolang
++rt jvm org.eolang:eo-runtime:0.28.10
++version 0.28.10
+
+[] > bool
+ # Equal to another object?
+ [x] > eq
+ eq. > @
+ ^.as-bytes
+ x.as-bytes
+
+ # If true, return "t", otherwise "f"
+ [t f] > if /t
+
+ # NOT
+ [] > not
+ eq. > @
+ ^
+ FALSE
+
+ # AND
+ [x...] > and /bool
+
+ # OR
+ [x...] > or /bool
+
+ # While this is true copies the object
+ # with "i" as the position of the cycle. The result
+ # of WHILE is the last dataized object or FALSE if
+ # ^ condition was never TRUE. The \rho of the object
+ # copied will be set to "while.\rho".
+ [f] > while /int
+
+ # Converts this to bytes
+ [] > as-bytes
+ if. > @
+ ^
+ 01-
+ 00-
+
+ # Converts this to hash
+ [] > as-hash
+ if. > @
+ ^
+ 1231
+ 1237
+
+
+
+ add-refs
+ expand-aliases
+ resolve-aliases
+
+ The MIT License (MIT)
+
+Copyright (c) 2016-2022 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.
+
+
+ architect
+ yegor256@gmail.com
+ yegor256@gmail.com
+
+
+ home
+ https://github.com/objectionary/eo
+ https://github.com/objectionary/eo
+
+
+ package
+ org.eolang
+ org.eolang
+
+
+ rt
+ jvm org.eolang:eo-runtime:0.28.10
+ jvm
+ org.eolang:eo-runtime:0.28.10
+
+
+ version
+ 0.28.10
+ 0.28.10
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 00
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 01
+ 00
+
+
+
+
+
+ 00 00 00 00 00 00 04 CF
+ 00 00 00 00 00 00 04 D5
+
+
+
+
+
+
diff --git a/src/test/resources/unit/in/inner_usages/basic/app.xmir b/src/test/resources/unit/in/inner_usages/basic/app.xmir
new file mode 100644
index 0000000..a749d72
--- /dev/null
+++ b/src/test/resources/unit/in/inner_usages/basic/app.xmir
@@ -0,0 +1,105 @@
+
+
+ [] > cat
+ [] > talk
+ QQ.io.stdout > @
+ "Meow!"
+ [dir] > move
+ QQ.io.stdout > @
+ dir
+
+[] > dog
+ [] > talk
+ QQ.io.stdout > @
+ "Woof!"
+ [dir] > move
+ QQ.io.stdout > @
+ dir
+ [] > smth
+ QQ.io.stdout > @
+ "smth"
+
+[x] > some_object
+ x.talk > heh
+ x.move "left" > @
+
+[x] > other_object
+ x.talk > @
+ x.smth > hih
+
+[] > app
+ some_object dog > so
+ so > @
+
+
+
+
+
+
+
+
+
+ Meow!
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Woof!
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ smth
+
+
+
+
+
+
+
+
+
+ left
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/test/resources/unit/in/inner_usages/several_parameters/app.xmir b/src/test/resources/unit/in/inner_usages/several_parameters/app.xmir
new file mode 100644
index 0000000..51e2110
--- /dev/null
+++ b/src/test/resources/unit/in/inner_usages/several_parameters/app.xmir
@@ -0,0 +1,106 @@
+
+
+ [] > cat
+ [] > talk
+ QQ.io.stdout > @
+ "Meow!"
+ [dir] > move
+ QQ.io.stdout > @
+ dir
+
+[] > dog
+ [] > talk
+ QQ.io.stdout > @
+ "Woof!"
+ [dir] > move
+ QQ.io.stdout > @
+ dir
+ [] > smth
+ QQ.io.stdout > @
+ "smth"
+
+[x y] > some_object
+ x.move "left" > @
+ y.talk > meh
+ y.smth > ff
+
+[x] > other_object
+ x.talk > @
+
+[] > app
+ some_object dog > so
+ so > @
+
+
+
+
+
+
+
+
+
+ Meow!
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Woof!
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ smth
+
+
+
+
+
+
+
+
+ left
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/test/resources/unit/in/instance_usages/basic/app.xmir b/src/test/resources/unit/in/instance_usages/basic/app.xmir
new file mode 100644
index 0000000..ed8e700
--- /dev/null
+++ b/src/test/resources/unit/in/instance_usages/basic/app.xmir
@@ -0,0 +1,106 @@
+
+
+ [] > cat
+ [] > talk
+ QQ.io.stdout > @
+ "Meow!"
+ [dir] > move
+ QQ.io.stdout > @
+ dir
+
+[] > dog
+ [] > talk
+ QQ.io.stdout > @
+ "Woof!"
+ [dir] > move
+ QQ.io.stdout > @
+ dir
+ [] > smth
+ QQ.io.stdout > @
+ "smth"
+
+[x y] > some_object
+ y.talk > ff
+
+[x] > other_object
+ x.smth > @
+
+[] > app
+ some_object dog > so
+ so.x.move "right" > @
+ so.y.smth > fg
+
+
+
+
+
+
+
+
+
+ Meow!
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Woof!
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ smth
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ right
+
+
+
+
+
+
+
diff --git a/target/classes/META-INF/aoi-l.kotlin_module b/target/classes/META-INF/aoi-l.kotlin_module
new file mode 100644
index 0000000..3be0480
Binary files /dev/null and b/target/classes/META-INF/aoi-l.kotlin_module differ
diff --git a/target/classes/org/objectionary/aoi/generate/PlGenerator.class b/target/classes/org/objectionary/aoi/generate/PlGenerator.class
new file mode 100644
index 0000000..7284ae7
Binary files /dev/null and b/target/classes/org/objectionary/aoi/generate/PlGenerator.class differ
diff --git a/target/classes/org/objectionary/aoi/generate/PlGeneratorKt.class b/target/classes/org/objectionary/aoi/generate/PlGeneratorKt.class
new file mode 100644
index 0000000..8ba4f5c
Binary files /dev/null and b/target/classes/org/objectionary/aoi/generate/PlGeneratorKt.class differ
diff --git a/target/classes/org/objectionary/aoi/generate/util/FileWriterKt.class b/target/classes/org/objectionary/aoi/generate/util/FileWriterKt.class
new file mode 100644
index 0000000..c3d7d96
Binary files /dev/null and b/target/classes/org/objectionary/aoi/generate/util/FileWriterKt.class differ
diff --git a/target/classes/org/objectionary/aoi/launch/AoiLauncherKt.class b/target/classes/org/objectionary/aoi/launch/AoiLauncherKt.class
new file mode 100644
index 0000000..7757bfa
Binary files /dev/null and b/target/classes/org/objectionary/aoi/launch/AoiLauncherKt.class differ
diff --git a/target/classes/org/objectionary/aoi/sources/SourcesExtractor.class b/target/classes/org/objectionary/aoi/sources/SourcesExtractor.class
new file mode 100644
index 0000000..d3534f0
Binary files /dev/null and b/target/classes/org/objectionary/aoi/sources/SourcesExtractor.class differ