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 + 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