|
|
@@ -1,7 +1,5 @@
|
|
|
import org.junit.jupiter.api.Test;
|
|
|
-import xyz.kwiecien.jfuck.operation.Initialization;
|
|
|
-import xyz.kwiecien.jfuck.operation.ModifyStackValueOperation;
|
|
|
-import xyz.kwiecien.jfuck.operation.WriteOperation;
|
|
|
+import xyz.kwiecien.jfuck.operation.*;
|
|
|
|
|
|
import java.io.IOException;
|
|
|
import java.lang.classfile.ClassFile;
|
|
|
@@ -10,9 +8,12 @@ import java.lang.constant.ClassDesc;
|
|
|
import java.lang.constant.MethodTypeDesc;
|
|
|
import java.nio.file.Files;
|
|
|
import java.nio.file.Path;
|
|
|
+import java.util.List;
|
|
|
import java.util.function.Consumer;
|
|
|
|
|
|
+import static java.lang.classfile.ClassFile.*;
|
|
|
import static java.lang.constant.ConstantDescs.*;
|
|
|
+import static xyz.kwiecien.jfuck.operation.BytecodeConstants.DATA_SIZE_CONSTANT_NAME;
|
|
|
|
|
|
public class OperationsTest {
|
|
|
@Test
|
|
|
@@ -21,25 +22,43 @@ public class OperationsTest {
|
|
|
.aload(0)
|
|
|
.invokespecial(CD_Object, INIT_NAME, MTD_void).return_();
|
|
|
|
|
|
- Consumer<CodeBuilder> mainCode = cb -> {
|
|
|
- new Initialization().appendBytecode().accept(cb);
|
|
|
- new ModifyStackValueOperation((byte) 0x30).appendBytecode().accept(cb);
|
|
|
- new WriteOperation().appendBytecode().accept(cb);
|
|
|
- cb.return_();
|
|
|
- };
|
|
|
+ Consumer<CodeBuilder> addCode = cb -> {
|
|
|
+ new Initialization().appendBytecode().accept(cb);
|
|
|
+ new ReadOperation().appendBytecode().accept(cb);
|
|
|
+ new ModifyPointerOperation(1).appendBytecode().accept(cb);
|
|
|
+ new ModifyStackValueOperation((byte) 6).appendBytecode().accept(cb);
|
|
|
+ new Loop(List.of(
|
|
|
+ new ModifyPointerOperation(-1),
|
|
|
+ new ModifyStackValueOperation((byte) -8),
|
|
|
+ new ModifyPointerOperation(1),
|
|
|
+ new ModifyStackValueOperation((byte) -1)
|
|
|
+ )).appendBytecode().accept(cb);
|
|
|
+ new ReadOperation().appendBytecode().accept(cb);
|
|
|
+ new Loop(List.of(
|
|
|
+ new ModifyPointerOperation(-1),
|
|
|
+ new ModifyStackValueOperation((byte) 1),
|
|
|
+ new ModifyPointerOperation(1),
|
|
|
+ new ModifyStackValueOperation((byte) -1)
|
|
|
+ )).appendBytecode().accept(cb);
|
|
|
+ new ModifyPointerOperation(-1).appendBytecode().accept(cb);
|
|
|
+ new WriteOperation().appendBytecode().accept(cb);
|
|
|
+ cb.return_();
|
|
|
+ };
|
|
|
|
|
|
- var bytes = ClassFile.of().build(ClassDesc.of("GenClass"), clb ->
|
|
|
- clb.withFlags(ClassFile.ACC_PUBLIC)
|
|
|
- .withMethod(
|
|
|
- INIT_NAME,
|
|
|
- MTD_void,
|
|
|
- ClassFile.ACC_PUBLIC,
|
|
|
- mb -> mb.withCode(initCode))
|
|
|
- .withMethod(
|
|
|
- "main",
|
|
|
- MethodTypeDesc.of(CD_void, CD_String.arrayType()),
|
|
|
- ClassFile.ACC_PUBLIC + ClassFile.ACC_STATIC,
|
|
|
- mb -> mb.withCode(mainCode)));
|
|
|
+ var bytes = ClassFile.of().build(ClassDesc.of("GenClass"), clb -> {
|
|
|
+ clb.withFlags(ACC_PUBLIC);
|
|
|
+ clb.withField(DATA_SIZE_CONSTANT_NAME, CD_int, ACC_STATIC | ACC_FINAL);
|
|
|
+ clb.withMethod(
|
|
|
+ INIT_NAME,
|
|
|
+ MTD_void,
|
|
|
+ ACC_PUBLIC,
|
|
|
+ mb -> mb.withCode(initCode))
|
|
|
+ .withMethod(
|
|
|
+ "main",
|
|
|
+ MethodTypeDesc.of(CD_void, CD_String.arrayType()),
|
|
|
+ ACC_PUBLIC + ACC_STATIC,
|
|
|
+ mb -> mb.withCode(addCode));
|
|
|
+ });
|
|
|
Files.write(Path.of("/tmp/GenClass.class"), bytes);
|
|
|
}
|
|
|
}
|