diff --git a/src/main/java/com/falsepattern/jfunge/Globals.java b/src/main/java/com/falsepattern/jfunge/Globals.java
index ccd0a64..330bb54 100644
--- a/src/main/java/com/falsepattern/jfunge/Globals.java
+++ b/src/main/java/com/falsepattern/jfunge/Globals.java
@@ -4,19 +4,5 @@ public class Globals {
public static final String VERSION = "1.0.0";
public static final int FUNGE_VERSION = 1 * 256 * 256 + 0 * 256 + 0;
public static final int HANDPRINT = 0xfa15e9a7; //"falsepat"
- public static final String LICENSE = "JFunge - A standard-conforming Befunge-98 and Trefunge-98 interpreter\n" +
- "Copyright (C) 2022 FalsePattern\n" +
- "\n" +
- "This program is free software: you can redistribute it and/or modify\n" +
- "it under the terms of the GNU General Public License as published by\n" +
- "the Free Software Foundation, either version 3 of the License, or\n" +
- "(at your option) any later version.\n" +
- "\n" +
- "This program is distributed in the hope that it will be useful,\n" +
- "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" +
- "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" +
- "GNU General Public License for more details.\n" +
- "\n" +
- "You should have received a copy of the GNU General Public License\n" +
- "along with this program. If not, see .";
+ public static final String LICENSE = "JFunge - A standard-conforming Befunge-98 and Trefunge-98 interpreter\n" + "Copyright (C) 2022 FalsePattern\n" + "\n" + "This program is free software: you can redistribute it and/or modify\n" + "it under the terms of the GNU General Public License as published by\n" + "the Free Software Foundation, either version 3 of the License, or\n" + "(at your option) any later version.\n" + "\n" + "This program is distributed in the hope that it will be useful,\n" + "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" + "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" + "GNU General Public License for more details.\n" + "\n" + "You should have received a copy of the GNU General Public License\n" + "along with this program. If not, see .";
}
diff --git a/src/main/java/com/falsepattern/jfunge/Main.java b/src/main/java/com/falsepattern/jfunge/Main.java
index 8b56ac1..696b462 100644
--- a/src/main/java/com/falsepattern/jfunge/Main.java
+++ b/src/main/java/com/falsepattern/jfunge/Main.java
@@ -4,7 +4,6 @@
import lombok.val;
import lombok.var;
-import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.file.Files;
@@ -12,7 +11,6 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
-import java.util.stream.Stream;
public class Main {
public static void main(String[] args) throws IOException {
@@ -61,7 +59,7 @@ public static void main(String[] args) throws IOException {
var read = 0;
val buf = new byte[4096];
while ((read = in.read(buf)) > 0) {
- programBytes.write(buf, 0, read);
+ programBytes.write(buf, 0, read);
}
program = programBytes.toByteArray();
} else {
diff --git a/src/main/java/com/falsepattern/jfunge/Releasable.java b/src/main/java/com/falsepattern/jfunge/Releasable.java
index 1d8ca91..e2d0084 100644
--- a/src/main/java/com/falsepattern/jfunge/Releasable.java
+++ b/src/main/java/com/falsepattern/jfunge/Releasable.java
@@ -1,6 +1,6 @@
package com.falsepattern.jfunge;
-public interface Releasable extends AutoCloseable{
+public interface Releasable extends AutoCloseable {
/**
* When called, it signals that this specific object is no longer referenced anywhere in the code, and can be freely deleted or even reused later by the provider.
*/
diff --git a/src/main/java/com/falsepattern/jfunge/interpreter/ExecutionContext.java b/src/main/java/com/falsepattern/jfunge/interpreter/ExecutionContext.java
index 9bd6895..0162e96 100644
--- a/src/main/java/com/falsepattern/jfunge/interpreter/ExecutionContext.java
+++ b/src/main/java/com/falsepattern/jfunge/interpreter/ExecutionContext.java
@@ -6,23 +6,37 @@
import java.io.OutputStream;
import java.util.List;
import java.util.Map;
-import java.util.Scanner;
public interface ExecutionContext {
InstructionPointer[] allIPs();
+
InstructionPointer IP();
+
InstructionPointer cloneIP();
+
FungeSpace fungeSpace();
+
int dimensions();
+
boolean stopped();
+
void stop(int exitCode);
+
int exitCode();
+
void interpret(int code);
+
void step(InstructionPointer ip);
+
List args();
+
Map env();
+
int input(boolean stagger);
+
OutputStream output();
+
byte[] readFile(String file);
+
boolean writeFile(String file, byte[] data);
}
diff --git a/src/main/java/com/falsepattern/jfunge/interpreter/Interpreter.java b/src/main/java/com/falsepattern/jfunge/interpreter/Interpreter.java
index 026dc06..a81737c 100644
--- a/src/main/java/com/falsepattern/jfunge/interpreter/Interpreter.java
+++ b/src/main/java/com/falsepattern/jfunge/interpreter/Interpreter.java
@@ -10,7 +10,9 @@
import lombok.val;
import lombok.var;
-import java.io.*;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;
@@ -61,6 +63,18 @@ public boolean writeFile(String file, byte[] data) throws IOException {
private int inputStagger;
+ public Interpreter(boolean trefunge, String[] args, InputStream input, OutputStream output, FileIOSupplier fileIOSupplier) {
+ this.args = Arrays.asList(args);
+ dimensions = trefunge ? 3 : 2;
+ baseInstructionManager.loadInstructionSet(Funge98.INSTANCE);
+ this.input = input;
+ this.output = output;
+ this.fileIOSupplier = fileIOSupplier;
+ val ip = new InstructionPointer();
+ ip.UUID = nextUUID++;
+ IPs.add(ip);
+ }
+
public static int executeProgram(boolean trefunge, String[] args, byte[] program, long iterLimit, InputStream input, OutputStream output, FileIOSupplier fileIOSupplier) {
val interpreter = new Interpreter(trefunge, args, input, output, fileIOSupplier);
interpreter.fungeSpace().loadFileAt(0, 0, 0, program, trefunge);
@@ -70,7 +84,8 @@ public static int executeProgram(boolean trefunge, String[] args, byte[] program
interpreter.tick();
step++;
}
- if (!interpreter.stopped()) throw new IllegalStateException("Program exceeded max iteration count!");
+ if (!interpreter.stopped())
+ throw new IllegalStateException("Program exceeded max iteration count!");
} else {
while (!interpreter.stopped()) {
interpreter.tick();
@@ -79,18 +94,6 @@ public static int executeProgram(boolean trefunge, String[] args, byte[] program
return interpreter.exitCode();
}
- public Interpreter(boolean trefunge, String[] args, InputStream input, OutputStream output, FileIOSupplier fileIOSupplier) {
- this.args = Arrays.asList(args);
- dimensions = trefunge ? 3 : 2;
- baseInstructionManager.loadInstructionSet(Funge98.INSTANCE);
- this.input = input;
- this.output = output;
- this.fileIOSupplier = fileIOSupplier;
- val ip = new InstructionPointer();
- ip.UUID = nextUUID++;
- IPs.add(ip);
- }
-
@Override
public InstructionPointer[] allIPs() {
return IPs.toArray(new InstructionPointer[0]);
@@ -137,7 +140,8 @@ public void interpret(int opcode) {
if ((instr = IP().instructionManager.fetch(opcode)) != null || (instr = baseInstructionManager.fetch(opcode)) != null) {
instr.process(this);
} else {
- if (opcode == 'r') throw new IllegalArgumentException("Language does not implement 'r' reflect instruction.");
+ if (opcode == 'r')
+ throw new IllegalArgumentException("Language does not implement 'r' reflect instruction.");
interpret('r');
}
}
@@ -228,11 +232,6 @@ public boolean writeFile(String file, byte[] data) {
}
}
- public interface FileIOSupplier {
- byte[] readFile(String file) throws IOException;
- boolean writeFile(String file, byte[] data) throws IOException;
- }
-
public void tick() {
currentIP = null;
for (int i = 0; i < IPs.size(); i++) {
@@ -248,8 +247,14 @@ public void tick() {
clone = null;
}
}
- for (val ip: IPs) {
+ for (val ip : IPs) {
step(ip);
}
}
+
+ public interface FileIOSupplier {
+ byte[] readFile(String file) throws IOException;
+
+ boolean writeFile(String file, byte[] data) throws IOException;
+ }
}
diff --git a/src/main/java/com/falsepattern/jfunge/interpreter/instructions/Funge98.java b/src/main/java/com/falsepattern/jfunge/interpreter/instructions/Funge98.java
index 8ce3bd2..dc68e72 100644
--- a/src/main/java/com/falsepattern/jfunge/interpreter/instructions/Funge98.java
+++ b/src/main/java/com/falsepattern/jfunge/interpreter/instructions/Funge98.java
@@ -68,10 +68,14 @@ public static void unloadFinger(ExecutionContext ctx) {
}
@Instr('>')
- public static void east(ExecutionContext ctx) {ctx.IP().delta.set(1, 0, 0);}
+ public static void east(ExecutionContext ctx) {
+ ctx.IP().delta.set(1, 0, 0);
+ }
@Instr('v')
- public static void south(ExecutionContext ctx) {ctx.IP().delta.set(0, 1, 0);}
+ public static void south(ExecutionContext ctx) {
+ ctx.IP().delta.set(0, 1, 0);
+ }
@Instr('h')
public static void high(ExecutionContext ctx) {
@@ -94,28 +98,52 @@ public static void away(ExecutionContext ctx) {
var random = Math.abs(ctx.IP().nextRandom());
if (ctx.dimensions() == 3) {
switch (random % 6) {
- case 0: east(ctx); break;
- case 1: south(ctx); break;
- case 2: west(ctx); break;
- case 3: north(ctx); break;
- case 4: high(ctx); break;
- case 5: low(ctx); break;
+ case 0:
+ east(ctx);
+ break;
+ case 1:
+ south(ctx);
+ break;
+ case 2:
+ west(ctx);
+ break;
+ case 3:
+ north(ctx);
+ break;
+ case 4:
+ high(ctx);
+ break;
+ case 5:
+ low(ctx);
+ break;
}
} else {
switch (random % 4) {
- case 0: east(ctx); break;
- case 1: south(ctx); break;
- case 2: west(ctx); break;
- case 3: north(ctx); break;
+ case 0:
+ east(ctx);
+ break;
+ case 1:
+ south(ctx);
+ break;
+ case 2:
+ west(ctx);
+ break;
+ case 3:
+ north(ctx);
+ break;
}
}
}
@Instr('<')
- public static void west(ExecutionContext ctx) {ctx.IP().delta.set(-1, 0, 0);}
+ public static void west(ExecutionContext ctx) {
+ ctx.IP().delta.set(-1, 0, 0);
+ }
@Instr('^')
- public static void north(ExecutionContext ctx) {ctx.IP().delta.set(0, -1, 0);}
+ public static void north(ExecutionContext ctx) {
+ ctx.IP().delta.set(0, -1, 0);
+ }
@Instr('[')
public static void turnLeft(ExecutionContext ctx) {
@@ -130,7 +158,9 @@ public static void turnRight(ExecutionContext ctx) {
}
@Instr('#')
- public static void trampoline(ExecutionContext ctx) {ctx.IP().position.add(ctx.IP().delta);}
+ public static void trampoline(ExecutionContext ctx) {
+ ctx.IP().position.add(ctx.IP().delta);
+ }
@Instr('j')
public static void jumpNTimes(ExecutionContext ctx) {
@@ -180,22 +210,34 @@ public static void printChar(ExecutionContext ctx) {
}
@Instr('r')
- public static void reflect(ExecutionContext ctx) {ctx.IP().delta.mul(-1);}
+ public static void reflect(ExecutionContext ctx) {
+ ctx.IP().delta.mul(-1);
+ }
@Instr('@')
- public static void die(ExecutionContext ctx) {ctx.IP().die();}
+ public static void die(ExecutionContext ctx) {
+ ctx.IP().die();
+ }
@Instr('$')
- public static void pop(ExecutionContext ctx) {ctx.IP().stackStack.TOSS().pop();}
+ public static void pop(ExecutionContext ctx) {
+ ctx.IP().stackStack.TOSS().pop();
+ }
@Instr('n')
- public static void clearStack(ExecutionContext ctx) {ctx.IP().stackStack.TOSS().clear();}
+ public static void clearStack(ExecutionContext ctx) {
+ ctx.IP().stackStack.TOSS().clear();
+ }
@Instr('_')
- public static void branchEastWest(ExecutionContext ctx) {ctx.interpret(ctx.IP().stackStack.TOSS().pop() == 0 ? '>' : '<');}
+ public static void branchEastWest(ExecutionContext ctx) {
+ ctx.interpret(ctx.IP().stackStack.TOSS().pop() == 0 ? '>' : '<');
+ }
@Instr('|')
- public static void branchNorthSouth(ExecutionContext ctx) {ctx.interpret(ctx.IP().stackStack.TOSS().pop() == 0 ? 'v' : '^');}
+ public static void branchNorthSouth(ExecutionContext ctx) {
+ ctx.interpret(ctx.IP().stackStack.TOSS().pop() == 0 ? 'v' : '^');
+ }
@Instr('m')
public static void branchHighLow(ExecutionContext ctx) {
@@ -234,25 +276,38 @@ public static void conditionalTurn(ExecutionContext ctx) {
}
@Instr('z')
- public static void noop(ExecutionContext ctx) {}
+ public static void noop(ExecutionContext ctx) {
+ }
@Instr('+')
- public static void add(ExecutionContext ctx) {binop(ctx, Integer::sum);}
+ public static void add(ExecutionContext ctx) {
+ binop(ctx, Integer::sum);
+ }
@Instr('-')
- public static void sub(ExecutionContext ctx) {binop(ctx, (a, b) -> a - b);}
+ public static void sub(ExecutionContext ctx) {
+ binop(ctx, (a, b) -> a - b);
+ }
@Instr('*')
- public static void mul(ExecutionContext ctx) {binop(ctx, (a, b) -> a * b);}
+ public static void mul(ExecutionContext ctx) {
+ binop(ctx, (a, b) -> a * b);
+ }
@Instr('`')
- public static void greater(ExecutionContext ctx) {binop(ctx, (a, b) -> a > b ? 1 : 0);}
+ public static void greater(ExecutionContext ctx) {
+ binop(ctx, (a, b) -> a > b ? 1 : 0);
+ }
@Instr('/')
- public static void div(ExecutionContext ctx) {binop(ctx, (a, b) -> b == 0 ? 0 : a / b);}
+ public static void div(ExecutionContext ctx) {
+ binop(ctx, (a, b) -> b == 0 ? 0 : a / b);
+ }
@Instr('%')
- public static void mod(ExecutionContext ctx) {binop(ctx, (a, b) -> b == 0 ? 0 : a % b);}
+ public static void mod(ExecutionContext ctx) {
+ binop(ctx, (a, b) -> b == 0 ? 0 : a % b);
+ }
@Instr('\\')
public static void swap(ExecutionContext ctx) {
@@ -293,7 +348,9 @@ public static void get(ExecutionContext ctx) {
}
@Instr('!')
- public static void logicalNot(ExecutionContext ctx) {stack(ctx, (toss) -> toss.push(toss.pop() == 0 ? 1 : 0));}
+ public static void logicalNot(ExecutionContext ctx) {
+ stack(ctx, (toss) -> toss.push(toss.pop() == 0 ? 1 : 0));
+ }
@Instr(':')
public static void duplicate(ExecutionContext ctx) {
@@ -583,6 +640,17 @@ public static void sysCall(ExecutionContext ctx) {
}
}
+ public static void stack(ExecutionContext ctx, Consumer runner) {
+ runner.accept(ctx.IP().stackStack.TOSS());
+ }
+
+ public static void binop(ExecutionContext ctx, BinaryOperator op) {
+ val TOSS = ctx.IP().stackStack.TOSS();
+ int b = TOSS.pop();
+ int a = TOSS.pop();
+ TOSS.push(op.op(a, b));
+ }
+
@Override
public void load(ObjIntConsumer instructionSet) {
InstructionSet.super.load(instructionSet);
@@ -596,23 +664,12 @@ public void load(ObjIntConsumer instructionSet) {
}
}
- public static void stack(ExecutionContext ctx, Consumer runner) {
- runner.accept(ctx.IP().stackStack.TOSS());
- }
-
- public static void binop(ExecutionContext ctx, BinaryOperator op) {
- val TOSS = ctx.IP().stackStack.TOSS();
- int b = TOSS.pop();
- int a = TOSS.pop();
- TOSS.push(op.op(a, b));
+ @Override
+ public void unload(IntConsumer instructionSet) {
+ throw new UnsupportedOperationException("Cannot unload the base syntax");
}
public interface BinaryOperator {
int op(int a, int b);
}
-
- @Override
- public void unload(IntConsumer instructionSet) {
- throw new UnsupportedOperationException("Cannot unload the base syntax");
- }
}
diff --git a/src/main/java/com/falsepattern/jfunge/interpreter/instructions/InstructionManager.java b/src/main/java/com/falsepattern/jfunge/interpreter/instructions/InstructionManager.java
index 1e6da37..88685df 100644
--- a/src/main/java/com/falsepattern/jfunge/interpreter/instructions/InstructionManager.java
+++ b/src/main/java/com/falsepattern/jfunge/interpreter/instructions/InstructionManager.java
@@ -1,7 +1,6 @@
package com.falsepattern.jfunge.interpreter.instructions;
import com.falsepattern.jfunge.Copiable;
-import com.falsepattern.jfunge.interpreter.instructions.fingerprints.Fingerprint;
import gnu.trove.map.TIntObjectMap;
import gnu.trove.map.hash.TIntObjectHashMap;
import lombok.NoArgsConstructor;
diff --git a/src/main/java/com/falsepattern/jfunge/interpreter/instructions/InstructionSet.java b/src/main/java/com/falsepattern/jfunge/interpreter/instructions/InstructionSet.java
index abcd6be..8023f8e 100644
--- a/src/main/java/com/falsepattern/jfunge/interpreter/instructions/InstructionSet.java
+++ b/src/main/java/com/falsepattern/jfunge/interpreter/instructions/InstructionSet.java
@@ -20,14 +20,7 @@ default void load(ObjIntConsumer instructionSet) {
val lookup = MethodHandles.lookup();
val methodType = MethodType.methodType(void.class, ExecutionContext.class);
try {
- val lambda = (Instruction) LambdaMetafactory.metafactory(lookup,
- "process",
- MethodType.methodType(Instruction.class),
- methodType,
- lookup.findStatic(clazz, method.getName(), methodType),
- methodType)
- .getTarget()
- .invokeExact();
+ val lambda = (Instruction) LambdaMetafactory.metafactory(lookup, "process", MethodType.methodType(Instruction.class), methodType, lookup.findStatic(clazz, method.getName(), methodType), methodType).getTarget().invokeExact();
val ann = method.getAnnotation(Instr.class);
instructionSet.accept(lambda, ann.value());
} catch (Throwable e) {
diff --git a/src/main/java/com/falsepattern/jfunge/interpreter/instructions/fingerprints/Fingerprint.java b/src/main/java/com/falsepattern/jfunge/interpreter/instructions/fingerprints/Fingerprint.java
index 45d29d2..b32cc85 100644
--- a/src/main/java/com/falsepattern/jfunge/interpreter/instructions/fingerprints/Fingerprint.java
+++ b/src/main/java/com/falsepattern/jfunge/interpreter/instructions/fingerprints/Fingerprint.java
@@ -1,6 +1,5 @@
package com.falsepattern.jfunge.interpreter.instructions.fingerprints;
-import com.falsepattern.jfunge.interpreter.instructions.Instruction;
import com.falsepattern.jfunge.interpreter.instructions.InstructionSet;
public interface Fingerprint extends InstructionSet {
diff --git a/src/main/java/com/falsepattern/jfunge/interpreter/instructions/fingerprints/MODE.java b/src/main/java/com/falsepattern/jfunge/interpreter/instructions/fingerprints/MODE.java
index ae33b91..6a1917b 100644
--- a/src/main/java/com/falsepattern/jfunge/interpreter/instructions/fingerprints/MODE.java
+++ b/src/main/java/com/falsepattern/jfunge/interpreter/instructions/fingerprints/MODE.java
@@ -36,11 +36,6 @@ public static void queueMode(ExecutionContext ctx) {
ctx.IP().stackStack.queueMode(!ctx.IP().stackStack.queueMode());
}
- @Override
- public int code() {
- return 0x4d4f4445;
- }
-
private static void toggleMode(ExecutionContext ctx, InstructionSet set, int bit) {
val ip = ctx.IP();
val state = ip.customStorage.get("mode");
@@ -54,6 +49,11 @@ private static void toggleMode(ExecutionContext ctx, InstructionSet set, int bit
ip.customStorage.put("mode", state ^ bit);
}
+ @Override
+ public int code() {
+ return 0x4d4f4445;
+ }
+
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public static final class HoverMode implements InstructionSet {
@Instr('>')
@@ -100,6 +100,7 @@ public static final class SwitchMode implements InstructionSet {
private static void set(ExecutionContext ctx, int ch) {
ctx.fungeSpace().set(ctx.IP().position, ch);
}
+
@Instr('(')
public static void loadFinger(ExecutionContext ctx) {
Funge98.loadFinger(ctx);
diff --git a/src/main/java/com/falsepattern/jfunge/interpreter/instructions/fingerprints/NULL.java b/src/main/java/com/falsepattern/jfunge/interpreter/instructions/fingerprints/NULL.java
index 29e1cd9..a1a25b3 100644
--- a/src/main/java/com/falsepattern/jfunge/interpreter/instructions/fingerprints/NULL.java
+++ b/src/main/java/com/falsepattern/jfunge/interpreter/instructions/fingerprints/NULL.java
@@ -10,6 +10,7 @@
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class NULL implements Fingerprint {
public static final NULL INSTANCE = new NULL();
+
@Override
public void load(ObjIntConsumer instructionSet) {
for (int i = 'A'; i <= 'Z'; i++) {
diff --git a/src/main/java/com/falsepattern/jfunge/interpreter/instructions/fingerprints/ROMA.java b/src/main/java/com/falsepattern/jfunge/interpreter/instructions/fingerprints/ROMA.java
index ad351b1..d5990e3 100644
--- a/src/main/java/com/falsepattern/jfunge/interpreter/instructions/fingerprints/ROMA.java
+++ b/src/main/java/com/falsepattern/jfunge/interpreter/instructions/fingerprints/ROMA.java
@@ -1,37 +1,47 @@
package com.falsepattern.jfunge.interpreter.instructions.fingerprints;
import com.falsepattern.jfunge.interpreter.ExecutionContext;
-import com.falsepattern.jfunge.interpreter.instructions.Instruction;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
-import java.util.function.IntConsumer;
-import java.util.function.ObjIntConsumer;
-
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class ROMA implements Fingerprint {
public static final ROMA INSTANCE = new ROMA();
@Instr('I')
- public static void I(ExecutionContext ctx) {ctx.IP().stackStack.TOSS().push(1);}
+ public static void I(ExecutionContext ctx) {
+ ctx.IP().stackStack.TOSS().push(1);
+ }
@Instr('V')
- public static void V(ExecutionContext ctx) {ctx.IP().stackStack.TOSS().push(5);}
+ public static void V(ExecutionContext ctx) {
+ ctx.IP().stackStack.TOSS().push(5);
+ }
@Instr('X')
- public static void X(ExecutionContext ctx) {ctx.IP().stackStack.TOSS().push(10);}
+ public static void X(ExecutionContext ctx) {
+ ctx.IP().stackStack.TOSS().push(10);
+ }
@Instr('L')
- public static void L(ExecutionContext ctx) {ctx.IP().stackStack.TOSS().push(50);}
+ public static void L(ExecutionContext ctx) {
+ ctx.IP().stackStack.TOSS().push(50);
+ }
@Instr('C')
- public static void C(ExecutionContext ctx) {ctx.IP().stackStack.TOSS().push(100);}
+ public static void C(ExecutionContext ctx) {
+ ctx.IP().stackStack.TOSS().push(100);
+ }
@Instr('D')
- public static void D(ExecutionContext ctx) {ctx.IP().stackStack.TOSS().push(500);}
+ public static void D(ExecutionContext ctx) {
+ ctx.IP().stackStack.TOSS().push(500);
+ }
@Instr('M')
- public static void M(ExecutionContext ctx) {ctx.IP().stackStack.TOSS().push(1000);}
+ public static void M(ExecutionContext ctx) {
+ ctx.IP().stackStack.TOSS().push(1000);
+ }
@Override
public int code() {
diff --git a/src/main/java/com/falsepattern/jfunge/ip/InstructionPointer.java b/src/main/java/com/falsepattern/jfunge/ip/InstructionPointer.java
index 9c5af58..9144dcf 100644
--- a/src/main/java/com/falsepattern/jfunge/ip/InstructionPointer.java
+++ b/src/main/java/com/falsepattern/jfunge/ip/InstructionPointer.java
@@ -17,12 +17,9 @@ public class InstructionPointer implements Copiable {
public final StackStack stackStack;
public final InstructionManager instructionManager;
public final TObjectIntMap customStorage;
-
+ private final SecureRandom rng;
public boolean stringMode = false;
public int UUID;
-
- private final SecureRandom rng;
-
@Getter
private boolean dead = false;
diff --git a/src/main/java/com/falsepattern/jfunge/ip/Stack.java b/src/main/java/com/falsepattern/jfunge/ip/Stack.java
index 38411f8..d4fe215 100644
--- a/src/main/java/com/falsepattern/jfunge/ip/Stack.java
+++ b/src/main/java/com/falsepattern/jfunge/ip/Stack.java
@@ -10,6 +10,7 @@ public class Stack implements Copiable {
private final TIntList storage;
public boolean invertMode;
public boolean queueMode;
+
public Stack() {
storage = new TIntArrayList();
}
@@ -108,7 +109,7 @@ public void pushString(String text) {
public String popString() {
val sb = new StringBuilder();
char c;
- while ((c = (char)pop()) != 0) {
+ while ((c = (char) pop()) != 0) {
sb.append(c);
}
return sb.toString();
diff --git a/src/main/java/com/falsepattern/jfunge/ip/StackStack.java b/src/main/java/com/falsepattern/jfunge/ip/StackStack.java
index 11c5725..a08cd3d 100644
--- a/src/main/java/com/falsepattern/jfunge/ip/StackStack.java
+++ b/src/main/java/com/falsepattern/jfunge/ip/StackStack.java
@@ -71,14 +71,15 @@ public int[] sizes() {
val sizes = new int[stackStack.size() + 1];
sizes[0] = TOSS().size();
int i = 1;
- for (val s: stackStack) {
+ for (val s : stackStack) {
sizes[i++] = s.size();
}
return sizes;
}
public boolean popStackStack() {
- if (stackStack.size() == 0) return false;
+ if (stackStack.size() == 0)
+ return false;
TOSS(stackStack.pop());
return true;
}
diff --git a/src/main/java/com/falsepattern/jfunge/storage/Bounds.java b/src/main/java/com/falsepattern/jfunge/storage/Bounds.java
index adf6337..b481435 100644
--- a/src/main/java/com/falsepattern/jfunge/storage/Bounds.java
+++ b/src/main/java/com/falsepattern/jfunge/storage/Bounds.java
@@ -4,7 +4,8 @@
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
-@Accessors(fluent = true, chain = true)
+@Accessors(fluent = true,
+ chain = true)
@Data
@NoArgsConstructor
public class Bounds implements BoundsC {
diff --git a/src/main/java/com/falsepattern/jfunge/storage/BoundsC.java b/src/main/java/com/falsepattern/jfunge/storage/BoundsC.java
index d83824d..fc99c56 100644
--- a/src/main/java/com/falsepattern/jfunge/storage/BoundsC.java
+++ b/src/main/java/com/falsepattern/jfunge/storage/BoundsC.java
@@ -5,10 +5,15 @@
public interface BoundsC> extends Copiable {
int xMin();
+
int yMin();
+
int zMin();
+
int xMax();
+
int yMax();
+
int zMax();
diff --git a/src/main/java/com/falsepattern/jfunge/storage/Chunk.java b/src/main/java/com/falsepattern/jfunge/storage/Chunk.java
index c8a3245..bf27747 100644
--- a/src/main/java/com/falsepattern/jfunge/storage/Chunk.java
+++ b/src/main/java/com/falsepattern/jfunge/storage/Chunk.java
@@ -84,6 +84,10 @@ public static int fromChunkZ(int cPos) {
return cPos * CHUNK_EDGE_SIZE_Z;
}
+ private static int toIndex(int x, int y, int z) {
+ return (z * CHUNK_EDGE_SIZE_Y + y) * CHUNK_EDGE_SIZE_X + x;
+ }
+
public boolean isEmpty() {
return populatedCells == 0;
}
@@ -95,10 +99,6 @@ public void release() {
}
}
- private static int toIndex(int x, int y, int z) {
- return (z * CHUNK_EDGE_SIZE_Y + y) * CHUNK_EDGE_SIZE_X + x;
- }
-
public int get(int x, int y, int z) {
return storage[toIndex(x, y, z)];
}
@@ -173,12 +173,6 @@ public Chunk deepCopy() {
}
private interface Getter {
- int toIndex(int a, int b, int c);
-
- int sa();
- int sb();
- int sc();
-
Getter gX = new Getter() {
public int toIndex(int a, int b, int c) {
return Chunk.toIndex(a, b, c);
@@ -239,5 +233,13 @@ public int sc() {
return CHUNK_EDGE_SIZE_Y;
}
};
+
+ int toIndex(int a, int b, int c);
+
+ int sa();
+
+ int sb();
+
+ int sc();
}
}
diff --git a/src/main/java/com/falsepattern/jfunge/storage/FungeSpace.java b/src/main/java/com/falsepattern/jfunge/storage/FungeSpace.java
index eee4e11..b209f39 100644
--- a/src/main/java/com/falsepattern/jfunge/storage/FungeSpace.java
+++ b/src/main/java/com/falsepattern/jfunge/storage/FungeSpace.java
@@ -3,7 +3,9 @@
import com.falsepattern.jfunge.Copiable;
import gnu.trove.map.TIntObjectMap;
import gnu.trove.map.hash.TIntObjectHashMap;
-import lombok.*;
+import lombok.RequiredArgsConstructor;
+import lombok.val;
+import lombok.var;
import org.joml.Vector3i;
import org.joml.Vector3ic;
@@ -16,12 +18,10 @@ public class FungeSpace implements Copiable {
private final TIntObjectMap>> storage = new TIntObjectHashMap<>();
private final Vector3i cachePos = new Vector3i();
- private Chunk cacheChunk;
-
- private boolean boundsRecheck = false;
private final Bounds bounds = new Bounds();
-
private final int defaultValue;
+ private Chunk cacheChunk;
+ private boolean boundsRecheck = false;
private FungeSpace(FungeSpace original) {
original.storage.forEachEntry((z, oPlane) -> {
@@ -46,6 +46,17 @@ private FungeSpace(FungeSpace original) {
cacheChunk = null;
}
+ private static void minMax(int[] arr, int[] buf) {
+ int max = Integer.MIN_VALUE;
+ int min = Integer.MAX_VALUE;
+ for (int i = 0; i < arr.length; i++) {
+ max = Math.max(arr[i], max);
+ min = Math.min(arr[i], min);
+ }
+ buf[0] = min;
+ buf[1] = max;
+ }
+
public int get(int x, int y, int z) {
val cX = toChunkX(x);
val cY = toChunkY(y);
@@ -91,7 +102,8 @@ public void set(int x, int y, int z, int value) {
}
var chunk = row.get(cX);
if (chunk == null) {
- if (value == defaultValue) return;
+ if (value == defaultValue)
+ return;
chunk = Chunk.allocate(defaultValue);
row.put(cX, chunk);
}
@@ -107,13 +119,13 @@ public void set(Vector3ic v, int value) {
public void gc() {
cacheChunk = null;
val planes = storage.keys();
- for (val iPlane: planes) {
+ for (val iPlane : planes) {
val plane = storage.get(iPlane);
val rows = plane.keys();
- for (val iRow: rows) {
+ for (val iRow : rows) {
val row = plane.get(iRow);
val chunks = row.keys();
- for (val iChunk: chunks) {
+ for (val iChunk : chunks) {
val chunk = row.get(iChunk);
if (chunk.isEmpty()) {
row.remove(iChunk);
@@ -146,7 +158,8 @@ public Vector3i loadFileAt(int x, int y, int z, byte[] data, boolean trefunge) {
int c = Byte.toUnsignedInt(data[i]);
switch (c) {
case '\r':
- if (i < data.length - 1 && data[i + 1] == '\n') continue;
+ if (i < data.length - 1 && data[i + 1] == '\n')
+ continue;
case '\n':
X = x;
Y++;
@@ -215,7 +228,8 @@ public BoundsC bounds() {
}
public void recheckBounds() {
- if (!boundsRecheck) return;
+ if (!boundsRecheck)
+ return;
gc();
boundsRecheck = false;
if (storage.size() == 0) {
@@ -259,7 +273,7 @@ public void recheckBounds() {
}
}
zMaxFinal = fromChunkZ(cZMax) + best;
- for (var cZ: cZArr) {
+ for (var cZ : cZArr) {
plane = storage.get(cZ);
int yMin;
int yMax;
@@ -289,7 +303,7 @@ public void recheckBounds() {
yMax = fromChunkY(cYMax) + best;
yMinFinal = Math.min(yMinFinal, yMin);
yMaxFinal = Math.max(yMaxFinal, yMax);
- for (val cY: cYArr) {
+ for (val cY : cYArr) {
row = plane.get(cY);
int xMin;
int xMax;
@@ -306,17 +320,6 @@ public void recheckBounds() {
bounds.set(xMinFinal, yMinFinal, zMinFinal, xMaxFinal, yMaxFinal, zMaxFinal);
}
- private static void minMax(int[] arr, int[] buf) {
- int max = Integer.MIN_VALUE;
- int min = Integer.MAX_VALUE;
- for (int i = 0; i < arr.length; i++) {
- max = Math.max(arr[i], max);
- min = Math.min(arr[i], min);
- }
- buf[0] = min;
- buf[1] = max;
- }
-
@Override
public FungeSpace deepCopy() {
return new FungeSpace(this);
diff --git a/src/test/java/com/falsepattern/jfunge/storage/TestChunk.java b/src/test/java/com/falsepattern/jfunge/storage/TestChunk.java
index d785000..c2e5a22 100644
--- a/src/test/java/com/falsepattern/jfunge/storage/TestChunk.java
+++ b/src/test/java/com/falsepattern/jfunge/storage/TestChunk.java
@@ -13,7 +13,8 @@ public class TestChunk {
@Test
public void testSetGet() {
val rngSeed = System.nanoTime();
- @Cleanup val chunk = Chunk.allocate(0);
+ @Cleanup
+ val chunk = Chunk.allocate(0);
var rng = new Random(rngSeed);
for (int z = 0; z < Chunk.CHUNK_EDGE_SIZE_Z; z++)
@@ -31,7 +32,8 @@ public void testSetGet() {
@Test
public void testDefaultValue() {
for (int i = -10; i < 10; i++) {
- @Cleanup val chunk = Chunk.allocate(i);
+ @Cleanup
+ val chunk = Chunk.allocate(i);
for (int z = 0; z < Chunk.CHUNK_EDGE_SIZE_Z; z++)
for (int y = 0; y < Chunk.CHUNK_EDGE_SIZE_Y; y++)
for (int x = 0; x < Chunk.CHUNK_EDGE_SIZE_X; x++)
@@ -41,7 +43,8 @@ public void testDefaultValue() {
@Test
public void testEmpty() {
- @Cleanup val chunk = Chunk.allocate(0);
+ @Cleanup
+ val chunk = Chunk.allocate(0);
Assertions.assertTrue(chunk.isEmpty());
chunk.set(1, 1, 0, 3);
Assertions.assertFalse(chunk.isEmpty());
diff --git a/src/test/java/com/falsepattern/jfunge/storage/TestFungeSpace.java b/src/test/java/com/falsepattern/jfunge/storage/TestFungeSpace.java
index 830d44d..5f02085 100644
--- a/src/test/java/com/falsepattern/jfunge/storage/TestFungeSpace.java
+++ b/src/test/java/com/falsepattern/jfunge/storage/TestFungeSpace.java
@@ -1,11 +1,9 @@
package com.falsepattern.jfunge.storage;
import lombok.val;
-import org.joml.Vector4i;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
-import java.awt.*;
import java.nio.charset.StandardCharsets;
import static com.falsepattern.jfunge.storage.Chunk.*;
@@ -15,6 +13,7 @@ private static int toPos(int fragment, int es) {
int sign = -((fragment >>> 1) & 1);
return sign + (1 + 2 * sign) * ((fragment & 1) * es);
}
+
@Test
public void testSetGet() {
val fungeSpace = new FungeSpace(0);
diff --git a/src/test/java/com/falsepattern/jfunge/storage/TestMycology.java b/src/test/java/com/falsepattern/jfunge/storage/TestMycology.java
index ea36423..586c4e0 100644
--- a/src/test/java/com/falsepattern/jfunge/storage/TestMycology.java
+++ b/src/test/java/com/falsepattern/jfunge/storage/TestMycology.java
@@ -6,42 +6,19 @@
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
-import java.io.*;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
public class TestMycology {
- @Test
- public void testMycology() {
- val input = new ByteArrayInputStream(new byte[0]);
- val output = new ByteArrayOutputStream();
- val program = new ByteArrayOutputStream();
- Assertions.assertDoesNotThrow(() -> {
- val reader = TestMycology.class.getResourceAsStream("/mycology.b98");
- Assertions.assertNotNull(reader);
- var read = 0;
- val b = new byte[4096];
- while ((read = reader.read(b)) > 0) {
- program.write(b, 0, read);
- }
- });
- val returnCode = Assertions.assertDoesNotThrow(() -> Interpreter.executeProgram(false, new String[]{"mycology.b98"}, program.toByteArray(), 300000, input, output, fakeSupplier));
- val txt = output.toString();
- Assertions.assertTrue(Arrays.stream(txt.split("\n")).noneMatch((line) -> {
- if (line.startsWith("BAD")) {
- System.out.println(line);
- return true;
- } else {
- return false;
- }
- }));
- Assertions.assertEquals(15, returnCode);
- }
-
private static final Interpreter.FileIOSupplier fakeSupplier = new Interpreter.FileIOSupplier() {
private final Map files = new HashMap<>();
+
@Override
public byte[] readFile(String file) throws IOException {
if (files.containsKey(file)) {
@@ -70,4 +47,31 @@ public boolean writeFile(String file, byte[] data) throws IOException {
return true;
}
};
+
+ @Test
+ public void testMycology() {
+ val input = new ByteArrayInputStream(new byte[0]);
+ val output = new ByteArrayOutputStream();
+ val program = new ByteArrayOutputStream();
+ Assertions.assertDoesNotThrow(() -> {
+ val reader = TestMycology.class.getResourceAsStream("/mycology.b98");
+ Assertions.assertNotNull(reader);
+ var read = 0;
+ val b = new byte[4096];
+ while ((read = reader.read(b)) > 0) {
+ program.write(b, 0, read);
+ }
+ });
+ val returnCode = Assertions.assertDoesNotThrow(() -> Interpreter.executeProgram(false, new String[]{"mycology.b98"}, program.toByteArray(), 300000, input, output, fakeSupplier));
+ val txt = output.toString();
+ Assertions.assertTrue(Arrays.stream(txt.split("\n")).noneMatch((line) -> {
+ if (line.startsWith("BAD")) {
+ System.out.println(line);
+ return true;
+ } else {
+ return false;
+ }
+ }));
+ Assertions.assertEquals(15, returnCode);
+ }
}