Skip to content

Commit

Permalink
feat(objectionary#376): add a few puzzles
Browse files Browse the repository at this point in the history
  • Loading branch information
volodya-lombrozo committed Aug 12, 2024
1 parent 6fa702e commit f636ee9
Show file tree
Hide file tree
Showing 28 changed files with 111 additions and 95 deletions.
61 changes: 28 additions & 33 deletions src/main/java/org/eolang/opeo/decompilation/DecompilerState.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,12 @@
package org.eolang.opeo.decompilation;

import java.util.Deque;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Optional;
import javax.swing.text.html.Option;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.eolang.opeo.ast.AstNode;
import org.eolang.opeo.ast.Opcode;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;

/**
Expand All @@ -44,6 +41,11 @@
@EqualsAndHashCode
public final class DecompilerState {

/**
* Remaining opcodes.
* Each method has an original list of opcodes which we decompile.
* When some agent decompiles an instruction, it removes it from this list.
*/
private final Deque<Opcode> opcodes;

/**
Expand Down Expand Up @@ -74,6 +76,12 @@ public DecompilerState(final OperandStack operands, final LocalVariables vars) {
this(new LinkedList<>(), operands, vars);
}

/**
* Constructor.
* @param opcodes Remaining opcodes.
* @param stack Operand stack.
* @param vars Method local variables.
*/
public DecompilerState(
final Deque<Opcode> opcodes,
final OperandStack stack,
Expand All @@ -84,52 +92,39 @@ public DecompilerState(
this.vars = vars;
}

/**
* Retrieve current bytecode instruction.
* @return Current bytecode instruction.
*/
public Opcode instruction() {
return Optional.ofNullable(this.opcodes.peek()).orElse(new Opcode(-1));
}

/**
* Check if there are any instructions left.
* @return True if there are instructions left.
*/
public boolean hasInstructions() {
return !this.opcodes.isEmpty();
}

public void move() {
/**
* Remove current instruction from the list.
* This is used when we decompile an instruction.
*/
public void decompileInstruction() {
if (!this.opcodes.isEmpty()) {
this.opcodes.pop();
}
}

/**
* Retrieve current bytecode instruction.
* @return Current bytecode instruction.
*/
public Opcode instruction() {
return Optional.ofNullable(this.opcodes.peek()).orElse(new Opcode(-100));
// final Iterator<AstNode> iterator = this.stack().iterator();
// while (iterator.hasNext()) {
// final AstNode next = iterator.next();
// if (next instanceof Opcode) {
// return (Opcode) next;
// }
// }
// throw new IllegalStateException(
// "No opcode found in the stack"
// );
// return (Opcode) this.stack().peek();
}

/**
* Instruction operand.
* @param index Operand index.
* @return Instruction operand.
*/
public Object operand(final int index) {
return this.instruction().operand(index);
// if (this.current.operands().size() <= index) {
// throw new IllegalStateException(
// String.format(
// "Instruction '%s' doesn't have operand at index '%d'",
// this.current,
// index
// )
// );
// }
// return this.current.operand(index);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public void handle(final DecompilerState state) {
final AstNode right = state.stack().pop();
final AstNode left = state.stack().pop();
state.stack().push(new Addition(left, right));
state.move();
state.decompileInstruction();
}
}

Expand Down
30 changes: 12 additions & 18 deletions src/main/java/org/eolang/opeo/decompilation/agents/AllAgents.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,22 @@
import org.eolang.opeo.decompilation.DecompilerState;
import org.eolang.opeo.decompilation.DecompilationAgent;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;

/**
* All agents that try to decompile incoming instructions.
* @since 0.2
* @checkstyle ClassFanOutComplexityCheck (500 lines)
* @todo #376:90min Decompilation Finish Condition.
* Currently we decompile until we out of instructions.
* But this might be incorrect when we start decompile high-level constructs.
* We should check decompilation stack instead.
* If it changes, we should continue. Otherwise, we should stop.
* The current implementation you can find here {@link #handle(DecompilerState)}.
* @todo #376:90min Unsupported Opcodes.
* Currently we have the ugly map {@link #agents} that contains instructions we can handle.
* We should refactor it to a more elegant solution.
* For example, each agent might provide a list of instructions it can decompile.
* By doing this we can infer the entire list of supported and unsupported instructions.
*/
public final class AllAgents implements DecompilationAgent {

Expand Down Expand Up @@ -142,15 +152,9 @@ private AllAgents(final Map<Integer, DecompilationAgent> agents) {

@Override
public void handle(final DecompilerState state) {
//todo: until?
while (state.hasInstructions()) {
this.agents.values().forEach(agent -> agent.handle(state));
// state.move();
}
// do {
// hash = state.hashCode();
// } while (hash != state.hashCode());
// this.agent(state.instruction().opcode()).handle(state);
}

/**
Expand All @@ -165,15 +169,6 @@ public String[] supportedOpcodes() {
.toArray(String[]::new);
}

/**
* Get instruction handler.
* @param opcode Instruction opcode.
* @return Instruction handler.
*/
// private DecompilationAgent agent(final int opcode) {
// return this.agents.getOrDefault(opcode, this.agents.get(AllAgents.UNIMPLEMENTED));
// }

/**
* Unimplemented instruction handler.
* @since 0.1
Expand Down Expand Up @@ -203,8 +198,7 @@ public void handle(final DecompilerState state) {
this.counting
)
);
state.move();

state.decompileInstruction();
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public final class BipushAgent implements DecompilationAgent {
public void handle(final DecompilerState state) {
if (BipushAgent.SUPPORTED.contains(state.instruction().opcode())) {
state.stack().push(new Literal(state.operand(0)));
state.move();
state.decompileInstruction();
}
}

Expand Down
35 changes: 26 additions & 9 deletions src/main/java/org/eolang/opeo/decompilation/agents/CastAgent.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@
import java.util.HashSet;
import java.util.Set;
import org.eolang.opeo.ast.Cast;
import org.eolang.opeo.decompilation.DecompilerState;
import org.eolang.opeo.decompilation.DecompilationAgent;
import org.eolang.opeo.decompilation.DecompilerState;
import org.objectweb.asm.Type;

/**
Expand All @@ -37,6 +37,9 @@
*/
public final class CastAgent implements DecompilationAgent {

/**
* Supported opcodes.
*/
private static final Set<Integer> SUPPROTED = new HashSet<>(
Arrays.asList(
org.objectweb.asm.Opcodes.I2B,
Expand Down Expand Up @@ -67,34 +70,47 @@ public void handle(final DecompilerState state) {
state.stack().pop()
)
);
state.move();
state.decompileInstruction();
}
}

/**
* Target type.
* @param opcode Opcode to handle.
* @return Target type.
*/
private static Type target(final int opcode) {
final Type result;
switch (opcode) {
case org.objectweb.asm.Opcodes.I2B:
return Type.BYTE_TYPE;
result = Type.BYTE_TYPE;
break;
case org.objectweb.asm.Opcodes.I2C:
return Type.CHAR_TYPE;
result = Type.CHAR_TYPE;
break;
case org.objectweb.asm.Opcodes.I2S:
return Type.SHORT_TYPE;
result = Type.SHORT_TYPE;
break;
case org.objectweb.asm.Opcodes.I2L:
case org.objectweb.asm.Opcodes.F2L:
case org.objectweb.asm.Opcodes.D2L:
return Type.LONG_TYPE;
result = Type.LONG_TYPE;
break;
case org.objectweb.asm.Opcodes.I2F:
case org.objectweb.asm.Opcodes.L2F:
case org.objectweb.asm.Opcodes.D2F:
return Type.FLOAT_TYPE;
result = Type.FLOAT_TYPE;
break;
case org.objectweb.asm.Opcodes.I2D:
case org.objectweb.asm.Opcodes.L2D:
case org.objectweb.asm.Opcodes.F2D:
return Type.DOUBLE_TYPE;
result = Type.DOUBLE_TYPE;
break;
case org.objectweb.asm.Opcodes.L2I:
case org.objectweb.asm.Opcodes.F2I:
case org.objectweb.asm.Opcodes.D2I:
return Type.INT_TYPE;
result = Type.INT_TYPE;
break;
default:
throw new IllegalArgumentException(
String.format(
Expand All @@ -103,5 +119,6 @@ private static Type target(final int opcode) {
)
);
}
return result;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public void handle(final DecompilerState state) {
final AstNode value = state.stack().pop();
final Object type = state.operand(0);
state.stack().push(new CheckCast(Type.getObjectType((String) type), value));
state.move();
state.decompileInstruction();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,11 @@
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import org.eolang.opeo.SelectiveDecompiler;
import org.eolang.opeo.ast.AstNode;
import org.eolang.opeo.ast.Literal;
import org.eolang.opeo.decompilation.DecompilerState;
import org.eolang.opeo.decompilation.DecompilationAgent;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;

/**
* Iconst instruction handler.
Expand Down Expand Up @@ -92,7 +90,7 @@ public void handle(final DecompilerState state) {
state.stack().push(res);
break;
}
state.move();
state.decompileInstruction();
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public void handle(final DecompilerState state) {
if (DupAgent.SUPPORTED.contains(state.instruction().opcode())) {
final OperandStack stack = state.stack();
stack.push(new Duplicate(stack.pop()));
state.move();
state.decompileInstruction();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public void handle(final DecompilerState state) {
.type("field")
)
);
state.move();
state.decompileInstruction();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public void handle(final DecompilerState state) {
final String method = (String) state.operand(1);
final String descriptor = (String) state.operand(2);
state.stack().push(new ClassField(klass, method, descriptor));
state.move();
state.decompileInstruction();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public void handle(final DecompilerState state) {
final AstNode first = stack.pop();
final Label operand = (Label) state.operand(0);
stack.push(new If(first, second, operand));
state.move();
state.decompileInstruction();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public void handle(final DecompilerState state) {
args
);
state.stack().push(node);
state.move();
state.decompileInstruction();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public void handle(final DecompilerState state) {
args
)
);
state.move();
state.decompileInstruction();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ public void handle(final DecompilerState state) {
new Super(target, args, descriptor, type, name)
);
}
state.move();
state.decompileInstruction();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public void handle(final DecompilerState state) {
args
)
);
state.move();
state.decompileInstruction();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public void handle(final DecompilerState state) {
args
)
);
state.move();
state.decompileInstruction();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public void handle(final DecompilerState state) {
new Label(String.class.cast(state.operand(0)))
);
state.stack().push(node);
state.move();
state.decompileInstruction();
}
}
}
Loading

0 comments on commit f636ee9

Please sign in to comment.