diff --git a/pom.xml b/pom.xml index e79f1d9d..5856c0a3 100644 --- a/pom.xml +++ b/pom.xml @@ -145,6 +145,12 @@ SOFTWARE. test + + org.junit.jupiter + junit-jupiter-engine + + test + org.junit.jupiter junit-jupiter-params @@ -158,8 +164,8 @@ SOFTWARE. test - org.junit.jupiter - junit-jupiter-engine + com.jcabi + jcabi-matchers test diff --git a/src/main/java/org/eolang/opeo/Instruction.java b/src/main/java/org/eolang/opeo/Instruction.java index 4c5e7315..67363f6c 100644 --- a/src/main/java/org/eolang/opeo/Instruction.java +++ b/src/main/java/org/eolang/opeo/Instruction.java @@ -23,6 +23,7 @@ */ package org.eolang.opeo; +import java.util.Collections; import java.util.List; import lombok.ToString; @@ -43,7 +44,7 @@ public final class Instruction { /** * Operands. */ - private final List operands; + private final List arguments; /** * Constructor. @@ -61,7 +62,7 @@ public Instruction(final int code, final Object... args) { */ private Instruction(final int code, final List args) { this.opcode = code; - this.operands = args; + this.arguments = args; } /** @@ -78,6 +79,14 @@ public int code() { * @return Operand */ public Object operand(final int index) { - return this.operands.get(index); + return this.arguments.get(index); + } + + /** + * Operands. + * @return Operands. + */ + public List operands() { + return Collections.unmodifiableList(this.arguments); } } diff --git a/src/main/java/org/eolang/opeo/ast/AstNode.java b/src/main/java/org/eolang/opeo/ast/AstNode.java index 2b9a64bc..d4776763 100644 --- a/src/main/java/org/eolang/opeo/ast/AstNode.java +++ b/src/main/java/org/eolang/opeo/ast/AstNode.java @@ -23,6 +23,8 @@ */ package org.eolang.opeo.ast; +import org.xembly.Directive; + /** * Abstract syntax tree node. * @since 0.1 @@ -32,15 +34,15 @@ public interface AstNode { /** * Print ast node and all it's children. * @return String output. - * @todo #8:90min Print output in XMIR format. - * Currently we just print decompilation output as a string. - * We need to print the output into XMIR format directly. - * By using EO XML we will be able to integrate - * this code with other plugins and, which is also important, - * we won't need to format the output manually. */ String print(); + /** + * Convert node to XMIR. + * @return XMIR XML. + */ + Iterable toXmir(); + /** * Node id. * @return Node id. diff --git a/src/main/java/org/eolang/opeo/ast/Constructor.java b/src/main/java/org/eolang/opeo/ast/Constructor.java index 28a01668..6368975d 100644 --- a/src/main/java/org/eolang/opeo/ast/Constructor.java +++ b/src/main/java/org/eolang/opeo/ast/Constructor.java @@ -23,8 +23,12 @@ */ package org.eolang.opeo.ast; +import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; +import org.eolang.opeo.vmachine.ObjectReference; +import org.xembly.Directive; +import org.xembly.Directives; /** * Constructor output node. @@ -47,6 +51,18 @@ public final class Constructor implements AstNode { */ private final List arguments; + /** + * Constructor. + * @param type Constructor type + * @param arguments Constructor arguments + */ + public Constructor( + final String type, + final AstNode... arguments + ) { + this(type, new ObjectReference(type).toString(), Arrays.asList(arguments)); + } + /** * Constructor. * @param type Constructor type @@ -72,6 +88,16 @@ public String print() { ); } + @Override + public Iterable toXmir() { + final Directives directives = new Directives(); + directives.add("o") + .attr("base", ".new") + .add("o").attr("base", this.type).up(); + this.arguments.stream().map(AstNode::toXmir).forEach(directives::append); + return directives.up(); + } + @Override public String identifier() { return this.reference; diff --git a/src/main/java/org/eolang/opeo/ast/Invocation.java b/src/main/java/org/eolang/opeo/ast/Invocation.java index 1b88971b..14b89359 100644 --- a/src/main/java/org/eolang/opeo/ast/Invocation.java +++ b/src/main/java/org/eolang/opeo/ast/Invocation.java @@ -23,9 +23,12 @@ */ package org.eolang.opeo.ast; +import java.util.Arrays; import java.util.List; import java.util.UUID; import java.util.stream.Collectors; +import org.xembly.Directive; +import org.xembly.Directives; /** * Invocation output node. @@ -48,6 +51,20 @@ public final class Invocation implements AstNode { */ private final List arguments; + /** + * Constructor. + * @param source Source or target on which the invocation is performed + * @param method Method name + * @param args Arguments + */ + public Invocation( + final AstNode source, + final String method, + final AstNode... args + ) { + this(source, method, Arrays.asList(args)); + } + /** * Constructor. * @param source Source or target on which the invocation is performed @@ -74,6 +91,16 @@ public String print() { ); } + @Override + public Iterable toXmir() { + final Directives directives = new Directives(); + directives.add("o") + .attr("base", String.format(".%s", this.method)) + .append(this.source.toXmir()); + this.arguments.stream().map(AstNode::toXmir).forEach(directives::append); + return directives.up(); + } + @Override public String identifier() { return UUID.randomUUID().toString(); diff --git a/src/main/java/org/eolang/opeo/ast/Literal.java b/src/main/java/org/eolang/opeo/ast/Literal.java index b34e2294..921e1686 100644 --- a/src/main/java/org/eolang/opeo/ast/Literal.java +++ b/src/main/java/org/eolang/opeo/ast/Literal.java @@ -24,6 +24,8 @@ package org.eolang.opeo.ast; import java.util.UUID; +import org.eolang.jeo.representation.directives.DirectivesData; +import org.xembly.Directive; /** * Literal output. @@ -44,6 +46,11 @@ public Literal(final Object value) { this.object = value; } + @Override + public Iterable toXmir() { + return new DirectivesData(this.object); + } + @Override public String print() { final String result; diff --git a/src/main/java/org/eolang/opeo/ast/Opcode.java b/src/main/java/org/eolang/opeo/ast/Opcode.java new file mode 100644 index 00000000..5caee04a --- /dev/null +++ b/src/main/java/org/eolang/opeo/ast/Opcode.java @@ -0,0 +1,84 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2016-2023 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. + */ +package org.eolang.opeo.ast; + +import java.util.Arrays; +import java.util.List; +import java.util.UUID; +import org.eolang.jeo.representation.directives.DirectivesInstruction; +import org.eolang.parser.XMIR; +import org.xembly.Directive; +import org.xembly.Transformers; +import org.xembly.Xembler; + +/** + * Opcode output node. + * @since 0.1 + */ +public final class Opcode implements AstNode { + + /** + * Opcode. + */ + private final int bytecode; + + /** + * Opcode operands. + */ + private final List operands; + + /** + * Constructor. + * @param opcode Opcode + * @param operands Opcode operands + */ + public Opcode(final int opcode, final Object... operands) { + this(opcode, Arrays.asList(operands)); + } + + /** + * Constructor. + * @param opcode Opcode + * @param operands Opcode operands + */ + public Opcode(final int opcode, final List operands) { + this.bytecode = opcode; + this.operands = operands; + } + + @Override + public String print() { + return new XMIR(new Xembler(this.toXmir(), new Transformers.Node()).xmlQuietly()).toEO(); + } + + @Override + public Iterable toXmir() { + return new DirectivesInstruction(this.bytecode, this.operands.toArray()); + } + + @Override + public String identifier() { + return UUID.randomUUID().toString(); + } +} diff --git a/src/main/java/org/eolang/opeo/ast/Root.java b/src/main/java/org/eolang/opeo/ast/Root.java index 1e3f916c..0b41c574 100644 --- a/src/main/java/org/eolang/opeo/ast/Root.java +++ b/src/main/java/org/eolang/opeo/ast/Root.java @@ -23,11 +23,14 @@ */ package org.eolang.opeo.ast; +import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.Optional; import java.util.UUID; import java.util.stream.Collectors; +import org.xembly.Directive; +import org.xembly.Directives; /** * Root node. @@ -52,6 +55,21 @@ public String print() { return this.children.stream().map(AstNode::print).collect(Collectors.joining("\n")); } + @Override + public Iterable toXmir() { + final Iterable result; + if (this.children.isEmpty()) { + result = Collections.emptyList(); + } else { + final Directives directives = new Directives(); + directives.add("o").attr("base", "tuple"); + this.children.stream().map(AstNode::toXmir).forEach(directives::append); + directives.up(); + result = directives; + } + return result; + } + /** * Find child by ID. * @param identifier ID diff --git a/src/main/java/org/eolang/opeo/vmachine/DecompilerMachine.java b/src/main/java/org/eolang/opeo/vmachine/DecompilerMachine.java index be0ad82e..26edd6a0 100644 --- a/src/main/java/org/eolang/opeo/vmachine/DecompilerMachine.java +++ b/src/main/java/org/eolang/opeo/vmachine/DecompilerMachine.java @@ -32,8 +32,8 @@ import org.eolang.opeo.ast.AstNode; import org.eolang.opeo.ast.Constructor; import org.eolang.opeo.ast.Invocation; -import org.eolang.opeo.ast.Keyword; import org.eolang.opeo.ast.Literal; +import org.eolang.opeo.ast.Opcode; import org.eolang.opeo.ast.Root; import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; @@ -188,7 +188,9 @@ public void handle(final Instruction instruction) { private class ReturnHandler implements InstructionHandler { @Override public void handle(final Instruction instruction) { - DecompilerMachine.this.root.append(new Keyword("return")); + DecompilerMachine.this.root.append( + new Opcode(instruction.code(), instruction.operands()) + ); } } @@ -254,8 +256,9 @@ public void handle(final Instruction instruction) { private class UnimplementedHandler implements InstructionHandler { @Override public void handle(final Instruction instruction) { - DecompilerMachine.this.root - .append(new Keyword(String.format("Unimplemented %s", instruction))); + DecompilerMachine.this.root.append( + new Opcode(instruction.code(), instruction.operands()) + ); } } diff --git a/src/main/java/org/eolang/opeo/vmachine/ObjectReference.java b/src/main/java/org/eolang/opeo/vmachine/ObjectReference.java index 12006132..fff75a93 100644 --- a/src/main/java/org/eolang/opeo/vmachine/ObjectReference.java +++ b/src/main/java/org/eolang/opeo/vmachine/ObjectReference.java @@ -50,7 +50,7 @@ public final class ObjectReference { * Constructor. * @param type Object type */ - ObjectReference(final String type) { + public ObjectReference(final String type) { this(type, ObjectReference.GLOBAL); } diff --git a/src/test/java/org/eolang/opeo/ast/ConstructorTest.java b/src/test/java/org/eolang/opeo/ast/ConstructorTest.java new file mode 100644 index 00000000..3d2efed1 --- /dev/null +++ b/src/test/java/org/eolang/opeo/ast/ConstructorTest.java @@ -0,0 +1,71 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2016-2023 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. + */ +package org.eolang.opeo.ast; + +import com.jcabi.matchers.XhtmlMatchers; +import org.hamcrest.MatcherAssert; +import org.junit.jupiter.api.Test; +import org.xembly.ImpossibleModificationException; +import org.xembly.Transformers; +import org.xembly.Xembler; + +/** + * Test case for {@link Constructor}. + * @since 0.1 + */ +class ConstructorTest { + + @Test + void transformsIntoXmir() throws ImpossibleModificationException { + MatcherAssert.assertThat( + String.format( + "We expect the following XML to be generated:%n%s%n", + String.join( + "\n", + "", + " ", + " 66 69 72 73 74", + " 73 65 63 6F 6E 64", + " 00 00 00 00 00 00 00 03", + "" + ) + ), + new Xembler( + new Constructor( + "A", + new Literal("first"), + new Literal("second"), + new Literal(3) + ).toXmir(), + new Transformers.Node() + ).xml(), + XhtmlMatchers.hasXPaths( + "/o[@base='.new']", + "/o[@base='.new']/o[@base='A']", + "/o[@base='.new']/o[@base='string' and @data='bytes']", + "/o[@base='.new']/o[@base='int' and @data='bytes']" + ) + ); + } +} diff --git a/src/test/java/org/eolang/opeo/ast/InvocationTest.java b/src/test/java/org/eolang/opeo/ast/InvocationTest.java new file mode 100644 index 00000000..9dd47ce9 --- /dev/null +++ b/src/test/java/org/eolang/opeo/ast/InvocationTest.java @@ -0,0 +1,68 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2016-2023 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. + */ +package org.eolang.opeo.ast; + +import com.jcabi.matchers.XhtmlMatchers; +import org.hamcrest.MatcherAssert; +import org.junit.jupiter.api.Test; +import org.xembly.ImpossibleModificationException; +import org.xembly.Transformers; +import org.xembly.Xembler; + +/** + * Test case for {@link Invocation}. + * @since 0.1 + */ +class InvocationTest { + + @Test + void transformsToXmir() throws ImpossibleModificationException { + MatcherAssert.assertThat( + String.format( + "We expect the following XMIRl to be generated:%n%s%n", + String.join( + "\n", + "", + " ", + " ", + " ", + " 62 61 7A", + "" + ) + ), + new Xembler( + new Invocation( + new Constructor("foo"), + "bar", + new Literal("baz") + ).toXmir(), + new Transformers.Node() + ).xml(), + XhtmlMatchers.hasXPaths( + "/o[@base='.bar']/o[@base='.new']/o[@base='foo']", + "/o[@base='.bar']/o[@base='string' and @data='bytes' and text()='62 61 7A']" + ) + ); + } +} diff --git a/src/test/java/org/eolang/opeo/ast/LiteralTest.java b/src/test/java/org/eolang/opeo/ast/LiteralTest.java new file mode 100644 index 00000000..927e8425 --- /dev/null +++ b/src/test/java/org/eolang/opeo/ast/LiteralTest.java @@ -0,0 +1,49 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2016-2023 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. + */ +package org.eolang.opeo.ast; + +import com.jcabi.matchers.XhtmlMatchers; +import org.hamcrest.MatcherAssert; +import org.junit.jupiter.api.Test; +import org.xembly.ImpossibleModificationException; +import org.xembly.Transformers; +import org.xembly.Xembler; + +/** + * Test case for {@link Literal}. + * @since 0.1 + */ +class LiteralTest { + + @Test + void transformsToXmir() throws ImpossibleModificationException { + MatcherAssert.assertThat( + "We expect the following XML to be generated: 4E 65 6F", + new Xembler(new Literal("Neo").toXmir(), new Transformers.Node()).xml(), + XhtmlMatchers.hasXPath( + "/o[@base='string' and @data='bytes' and text()='4E 65 6F']/text()" + ) + ); + } +} diff --git a/src/test/java/org/eolang/opeo/ast/OpcodeTest.java b/src/test/java/org/eolang/opeo/ast/OpcodeTest.java new file mode 100644 index 00000000..fc8a36a9 --- /dev/null +++ b/src/test/java/org/eolang/opeo/ast/OpcodeTest.java @@ -0,0 +1,70 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2016-2023 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. + */ +package org.eolang.opeo.ast; + +import com.jcabi.matchers.XhtmlMatchers; +import org.hamcrest.MatcherAssert; +import org.hamcrest.Matchers; +import org.junit.jupiter.api.Test; +import org.objectweb.asm.Opcodes; +import org.xembly.Transformers; +import org.xembly.Xembler; + +/** + * Test case for {@link Opcode}. + * @since 0.1 + */ +class OpcodeTest { + + @Test + void transformsToXml() { + MatcherAssert.assertThat( + String.format( + "We expect the following XML to be generated: %s", + "00 00 00 00 00 00 00 1268 65 6C 6C 6F" + ), + new Xembler( + new Opcode(Opcodes.LDC, "hello").toXmir(), + new Transformers.Node() + ).xmlQuietly(), + Matchers.allOf( + XhtmlMatchers.hasXPath("./o[@base='opcode']/o[@base='int']"), + XhtmlMatchers.hasXPath("./o[@base='opcode']/o[@base='string']") + ) + ); + } + + @Test + void prints() { + MatcherAssert.assertThat( + "We expect the following string to be printed: 'opcode > LDC-1\n 18\n \"bye\"'", + new Opcode(Opcodes.LDC, "bye").print(), + Matchers.allOf( + Matchers.containsString("opcode > LDC"), + Matchers.containsString("18"), + Matchers.containsString("bye") + ) + ); + } +} diff --git a/src/test/java/org/eolang/opeo/ast/RootTest.java b/src/test/java/org/eolang/opeo/ast/RootTest.java new file mode 100644 index 00000000..151f2eab --- /dev/null +++ b/src/test/java/org/eolang/opeo/ast/RootTest.java @@ -0,0 +1,74 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2016-2023 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. + */ +package org.eolang.opeo.ast; + +import com.jcabi.matchers.XhtmlMatchers; +import org.hamcrest.MatcherAssert; +import org.hamcrest.Matchers; +import org.junit.jupiter.api.Test; +import org.objectweb.asm.Opcodes; +import org.xembly.ImpossibleModificationException; +import org.xembly.Transformers; +import org.xembly.Xembler; + +/** + * Test case for {@link Root}. + * @since 0.1 + */ +class RootTest { + + @Test + void combinesAllChildElementsIntoSingleXmir() throws ImpossibleModificationException { + final Root root = new Root(); + root.append(new Literal("Wake up, Neo...")); + root.append(new Opcode(Opcodes.RETURN)); + root.append(new Literal(1)); + MatcherAssert.assertThat( + String.format( + "We expected to get the following XMIR:%n%s%n", + String.join( + "\n", + "", + " 57 61 6B 65 20 75 70 2C 20 4E 65 6F 2E 2E 2E", + " ", + " 00 00 00 00 00 00 00 B1", + " ", + " 00 00 00 00 00 00 00 01", + "" + ) + ), + new Xembler(root.toXmir(), new Transformers.Node()).xml(), + Matchers.allOf( + XhtmlMatchers.hasXPath("/o[@base='tuple']"), + XhtmlMatchers.hasXPath("/o[@base='tuple']/o[@base='string' and @data='bytes']"), + XhtmlMatchers.hasXPath( + "/o[@base='tuple']/o[@base='opcode' and contains(@name,'RETURN')]" + ), + XhtmlMatchers.hasXPath( + "/o[@base='tuple']/o[@base='int' and @data='bytes' and text()='00 00 00 00 00 00 00 01']" + ) + ) + ); + } +} diff --git a/src/main/java/org/eolang/opeo/ast/Keyword.java b/src/test/java/org/eolang/opeo/ast/package-info.java similarity index 72% rename from src/main/java/org/eolang/opeo/ast/Keyword.java rename to src/test/java/org/eolang/opeo/ast/package-info.java index 9e0fccdd..d45fc7f2 100644 --- a/src/main/java/org/eolang/opeo/ast/Keyword.java +++ b/src/test/java/org/eolang/opeo/ast/package-info.java @@ -21,36 +21,8 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -package org.eolang.opeo.ast; - -import java.util.UUID; - /** - * Keyword output. + * Test cases for the ast nodes. * @since 0.1 */ -public final class Keyword implements AstNode { - - /** - * Keyword. - */ - private final String word; - - /** - * Constructor. - * @param word Keyword - */ - public Keyword(final String word) { - this.word = word; - } - - @Override - public String print() { - return this.word; - } - - @Override - public String identifier() { - return UUID.randomUUID().toString(); - } -} +package org.eolang.opeo.ast; diff --git a/src/test/java/org/eolang/opeo/vmachine/DecompilerMachineTest.java b/src/test/java/org/eolang/opeo/vmachine/DecompilerMachineTest.java index 92e702d0..0c60de7a 100644 --- a/src/test/java/org/eolang/opeo/vmachine/DecompilerMachineTest.java +++ b/src/test/java/org/eolang/opeo/vmachine/DecompilerMachineTest.java @@ -59,8 +59,9 @@ void decompilesNewInstructions() { new Instruction(Opcodes.POP), new Instruction(Opcodes.RETURN) ), - Matchers.equalTo( - "B.new (A.new (42))\nreturn" + Matchers.allOf( + Matchers.containsString("B.new (A.new (42))"), + Matchers.containsString("opcode > RETURN") ) ); } @@ -90,8 +91,9 @@ void decompilesNewInstructionsEachWithParam() { new Instruction(Opcodes.POP), new Instruction(Opcodes.RETURN) ), - Matchers.equalTo( - "D.new (C.new (43)) (44) (45)\nreturn" + Matchers.allOf( + Matchers.containsString("D.new (C.new (43)) (44) (45)"), + Matchers.containsString("opcode > RETURN") ) ); }