diff --git a/src/it/optimization/pom.xml b/src/it/optimization/pom.xml
index d52a4a59a..e044e492e 100644
--- a/src/it/optimization/pom.xml
+++ b/src/it/optimization/pom.xml
@@ -28,7 +28,12 @@ SOFTWARE.
jeo-it
@project.version@
jar
- Integration test
+ Integration test that tries to transform simple java program
+ into XMIR and back. The integration test also checks that program can run
+ successfully and the plugin didn't break anything.
+ If you need to run only this test, use the following command:
+ "mvn clean integration-test invoker:run -Dinvoker.test=optimization -DskipTests"
+
UTF-8
1.8
diff --git a/src/it/optimization/src/main/java/org/eolang/jeo/Application.java b/src/it/optimization/src/main/java/org/eolang/jeo/Application.java
index 94ed6e37b..873301149 100644
--- a/src/it/optimization/src/main/java/org/eolang/jeo/Application.java
+++ b/src/it/optimization/src/main/java/org/eolang/jeo/Application.java
@@ -2,6 +2,17 @@
public class Application {
public static void main(String[] args) {
- System.out.println("Hello, World!");
+ if (bar(1.0d) < 7) {
+ System.out.println("Hello, World!");
+ } else {
+ System.out.println("Wake up, Neo...");
+ }
+ }
+
+ private static int bar(double x) {
+ if (x > 0.0d) {
+ return 5;
+ }
+ return 8;
}
}
diff --git a/src/main/java/org/eolang/jeo/representation/bytecode/CommandInstruction.java b/src/main/java/org/eolang/jeo/representation/bytecode/CommandInstruction.java
index 9d0eaa480..953f789b6 100644
--- a/src/main/java/org/eolang/jeo/representation/bytecode/CommandInstruction.java
+++ b/src/main/java/org/eolang/jeo/representation/bytecode/CommandInstruction.java
@@ -130,6 +130,13 @@ private enum Instruction {
visitor.visitInsn(Opcodes.DCONST_0)
),
+ /**
+ * Load the double value 1 onto the stack.
+ */
+ DCONST_1(Opcodes.DCONST_1, (visitor, arguments) ->
+ visitor.visitInsn(Opcodes.DCONST_1)
+ ),
+
/**
* Push a byte onto the stack as an integer value.
*/
@@ -228,6 +235,36 @@ private enum Instruction {
)
),
+ /**
+ * If value1 is greater than or equal to value2, branch to instruction at branchoffset.
+ */
+ IF_ICMPGE(Opcodes.IF_ICMPGE, (visitor, arguments) ->
+ visitor.visitJumpInsn(
+ Opcodes.IF_ICMPGE,
+ (org.objectweb.asm.Label) arguments.get(0)
+ )
+ ),
+
+ /**
+ * If value1 is less than or equal to value2, branch to instruction at branchoffset.
+ */
+ IF_ICMPLE(Opcodes.IF_ICMPLE, (visitor, arguments) ->
+ visitor.visitJumpInsn(
+ Opcodes.IF_ICMPLE,
+ (org.objectweb.asm.Label) arguments.get(0)
+ )
+ ),
+
+ /**
+ * Goes to another instruction at branchoffset.
+ */
+ GOTO(Opcodes.GOTO, (visitor, arguments) ->
+ visitor.visitJumpInsn(
+ Opcodes.GOTO,
+ (org.objectweb.asm.Label) arguments.get(0)
+ )
+ ),
+
/**
* Return an integer from a method.
*/
@@ -303,7 +340,7 @@ private enum Instruction {
* Invoke instance method on object objectref and puts the result on the stack.
* Might be void. The method is identified by method reference index in constant pool.
*/
- INCOKESPECIAL(Opcodes.INVOKESPECIAL, (visitor, arguments) ->
+ INVOKESPECIAL(Opcodes.INVOKESPECIAL, (visitor, arguments) ->
visitor.visitMethodInsn(
Opcodes.INVOKESPECIAL,
String.valueOf(arguments.get(0)),
@@ -313,6 +350,19 @@ private enum Instruction {
)
),
+ /**
+ * Invoke a class (static) method.
+ */
+ INVOKESTATIC(Opcodes.INVOKESTATIC, (visitor, arguments) ->
+ visitor.visitMethodInsn(
+ Opcodes.INVOKESTATIC,
+ String.valueOf(arguments.get(0)),
+ String.valueOf(arguments.get(1)),
+ String.valueOf(arguments.get(2)),
+ false
+ )
+ ),
+
/**
* Create new object of type identified by class reference in constant pool index.
*/
diff --git a/src/main/java/org/eolang/jeo/representation/xmir/HexString.java b/src/main/java/org/eolang/jeo/representation/xmir/HexString.java
index 1ba7aea63..bd4772c79 100644
--- a/src/main/java/org/eolang/jeo/representation/xmir/HexString.java
+++ b/src/main/java/org/eolang/jeo/representation/xmir/HexString.java
@@ -59,10 +59,17 @@ final class HexString {
* @return Human-readable string.
*/
String decode() {
- return Arrays.stream(this.hex.split(" "))
- .map(ch -> (char) Integer.parseInt(ch, HexString.RADIX))
- .map(String::valueOf)
- .collect(Collectors.joining());
+ try {
+ return Arrays.stream(this.hex.split(" "))
+ .map(ch -> (char) Integer.parseInt(ch, HexString.RADIX))
+ .map(String::valueOf)
+ .collect(Collectors.joining());
+ } catch (final NumberFormatException exception) {
+ throw new IllegalArgumentException(
+ String.format("Invalid hex string: %s", this.hex),
+ exception
+ );
+ }
}
/**
diff --git a/src/main/java/org/eolang/jeo/representation/xmir/XmlInstruction.java b/src/main/java/org/eolang/jeo/representation/xmir/XmlInstruction.java
index 91cfc6d41..69e11892b 100644
--- a/src/main/java/org/eolang/jeo/representation/xmir/XmlInstruction.java
+++ b/src/main/java/org/eolang/jeo/representation/xmir/XmlInstruction.java
@@ -31,6 +31,7 @@
import java.util.stream.IntStream;
import org.eolang.jeo.representation.HexData;
import org.eolang.jeo.representation.bytecode.BytecodeMethod;
+import org.objectweb.asm.Label;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
@@ -147,6 +148,12 @@ Node node() {
* Get opcode arguments.
* @param node Node.
* @return Arguments.
+ * @todo #234:90min Refactor XmlInstruction#arguments method.
+ * This method is too complex and has too many responsibilities.
+ * Moreover, it uses static field LABELS. We have to refactor this method in order
+ * to avoid all that problems. Don't forget to remove PMD and checkstyle comments about
+ * suppressed warnings.
+ * @checkstyle NestedIfDepthCheck (100 lines)
*/
private static Object[] arguments(final Node node) {
final NodeList children = node.getChildNodes();
@@ -157,6 +164,15 @@ private static Object[] arguments(final Node node) {
final NamedNodeMap attributes = child.getAttributes();
if (attributes.getNamedItem("base").getNodeValue().equals("int")) {
res.add(new HexString(child.getTextContent()).decodeAsInt());
+ } else if (attributes.getNamedItem("base").getNodeValue().equals("label")) {
+ final String uid = child.getTextContent().strip().replace("\n", "");
+ if (XmlLabel.LABELS.containsKey(uid)) {
+ res.add(XmlLabel.LABELS.get(uid));
+ } else {
+ final Label value = new Label();
+ XmlLabel.LABELS.put(uid, value);
+ res.add(value);
+ }
} else {
res.add(new HexString(child.getTextContent()).decode());
}
diff --git a/src/main/java/org/eolang/jeo/representation/xmir/XmlLabel.java b/src/main/java/org/eolang/jeo/representation/xmir/XmlLabel.java
index 1c28b39c4..6bf0afece 100644
--- a/src/main/java/org/eolang/jeo/representation/xmir/XmlLabel.java
+++ b/src/main/java/org/eolang/jeo/representation/xmir/XmlLabel.java
@@ -36,14 +36,13 @@ public final class XmlLabel implements XmlCommand {
/**
* All Labels.
- * @todo #226:90min Continue implementation of conditional instructions transformation.
- * Currently we parse bytecode and correctly save all labels into XMIR. Although the back
- * transformation is not implemented yet. We need to implement it and add or change integration
- * tests to check that conditional instructions are correctly transformed.
- * Moreover, we have to remove static field LABELS and use different approach to find labels.
+ * @todo #234:90min Hide LABELS Public Static Variable.
+ * It is not a good idea to expose LABELS and use static variable in general.
+ * We definitely have to hide this variable or, what is even better, get rid of it and create
+ * one more class that will encapsulate the LABELS logic.
* @checkstyle StaticVariableNameCheck (3 lines)
*/
- private static final Map LABELS = new ConcurrentHashMap<>();
+ public static final Map LABELS = new ConcurrentHashMap<>();
/**
* Label node.