mirror of
https://github.com/GTNewHorizons/ForgeMultipart.git
synced 2026-11-14 01:14:19 +00:00
refactor: modernize Scala signature switches
This commit is contained in:
1 parent
fa0bd01ab2
commit
c60abe790c
3 files changed
+54
-75
No files matched your search
@@ -4,9 +4,9 @@
|
||||
|
||||
The scoped integration is implemented on `algent/java`, building on baseline `65d0cd0`. The three regression fixes
|
||||
are preserved. `build.gradle` adds two tasks; `StackAnalyserLogic.visitInsn` uses the validated Java 21 pattern switch,
|
||||
while `JavaTraitRegistration` and `ClassInfoLookup` use Java 21 pattern variables. The nine Scala sources, Scala 2.11.5
|
||||
dependency, source layout, and normal Gradle entry points remain in place. Production tasks do not read a frozen jar
|
||||
or any files under `run/jvmdg-trial/`.
|
||||
`JavaTraitRegistration` and `ClassInfoLookup` use Java 21 pattern variables, and `ScalaSignatureParser` uses switch
|
||||
expressions. The nine Scala sources, Scala 2.11.5 dependency, source layout, and normal Gradle entry points remain in
|
||||
place. Production tasks do not read a frozen jar or any files under `run/jvmdg-trial/`.
|
||||
|
||||
The subsequent `StackAnalyser` initializer extraction is recorded in `JAVA_MIGRATION_HANDOFF.md`. The exact-byte
|
||||
comparisons and frozen-version reproduction below describe checkpoint `5f0e329`; later helper edits need their own
|
||||
@@ -75,9 +75,10 @@ Recommended order:
|
||||
1. Start with package-private helpers called directly by retained Scala. `JavaTraitRegistration.java` and
|
||||
`ClassInfoLookup.java` are completed follow-ups; pattern variables remove their checked casts without changing the
|
||||
Scala-facing declarations. `StackAnalyserLogic.java` remains the original proven example.
|
||||
2. Continue only where modern syntax produces a concrete control-flow gain. `ScalaSignatureParser.java` is the next
|
||||
useful candidate because its two result-producing switches can become exhaustive switch expressions.
|
||||
`ScalaTraitRegistration.java` should not move merely to restyle its erased `Some` checks.
|
||||
2. Continue only where modern syntax produces a concrete control-flow gain. `ScalaSignatureParser.java` is complete:
|
||||
its two result-producing switches are now switch expressions. Prefer simplifying the remaining opcode switches in
|
||||
the already-modern `StackAnalyserLogic.java` before adding another build exclusion. `ScalaTraitRegistration.java`
|
||||
should not move merely to restyle its erased `Some` checks.
|
||||
3. Consider public core implementations such as `RedstoneInteractions$.java`, `TileMultipart.java` and the registries
|
||||
only after the internal batches. Modern method bodies are technically possible, but their published ABI and frozen
|
||||
behavior make the review cost higher.
|
||||
@@ -106,6 +107,11 @@ The completed `ClassInfoLookup` batch has the same clean-build, 576-test, Java 8
|
||||
metadata as annotations for this helper's anonymous callbacks, but the packaged classes contain no executable JVM
|
||||
Downgrader API reference and the Java 8 runtime needs no added dependency.
|
||||
|
||||
The completed `ScalaSignatureParser` batch also passes the clean compiler boundary, all 576 JVM tests, all 289 Java 8
|
||||
Forge tests and the 134-dump comparison; all 450 packaged classes remain version 52. Its non-private ABI is unchanged
|
||||
and it has no executable JVM Downgrader API reference. Modern string concatenation in the same internal class lowers
|
||||
to six private helper methods; these are compiler implementation details, not consumer entry points.
|
||||
|
||||
### fastutil audit
|
||||
|
||||
GTNHLib 0.11.44 currently contributes `it.unimi.dsi:fastutil:8.5.18` to `compileClasspath`. It does **not** contribute
|
||||
@@ -165,8 +171,8 @@ scoped path selectively; if parsing, compilation order, ABI or downgrade support
|
||||
working syntax and record the blocker and revisit condition. Do not add fragile workarounds solely for syntax.
|
||||
|
||||
The production source tree now contains 231 Java files and nine Scala files / 782 nonblank Scala lines. Of the 224 Java
|
||||
sources in the Scala source tree, only `StackAnalyserLogic`, `JavaTraitRegistration` and `ClassInfoLookup` bypass joint
|
||||
compilation. Retained models, trait
|
||||
sources in the Scala source tree, only `StackAnalyserLogic`, `JavaTraitRegistration`, `ClassInfoLookup` and
|
||||
`ScalaSignatureParser` bypass joint compilation. Retained models, trait
|
||||
metadata, synthetic super accessors, and downstream Scala consumers prevent treating the last nine files as a
|
||||
mechanical deletion queue. Modern GTNH runtime support does not remove the retained Scala compiler's Java 8
|
||||
requirement. The main migration plan and working handoff carry the current API/adoption priorities and source counts.
|
||||
|
||||
@@ -15,6 +15,7 @@ def modernJavaSources = sourceSets.main.scala.matching {
|
||||
include 'codechicken/multipart/asm/StackAnalyserLogic.java'
|
||||
include 'codechicken/multipart/asm/JavaTraitRegistration.java'
|
||||
include 'codechicken/multipart/asm/ClassInfoLookup.java'
|
||||
include 'codechicken/multipart/asm/ScalaSignatureParser.java'
|
||||
}
|
||||
def legacyScala = tasks.named('compileScala') {
|
||||
// Zinc does not invalidate joint-compiled Java annotations when Tags.VERSION changes.
|
||||
@@ -23,6 +24,7 @@ def legacyScala = tasks.named('compileScala') {
|
||||
exclude 'codechicken/multipart/asm/StackAnalyserLogic.java'
|
||||
exclude 'codechicken/multipart/asm/JavaTraitRegistration.java'
|
||||
exclude 'codechicken/multipart/asm/ClassInfoLookup.java'
|
||||
exclude 'codechicken/multipart/asm/ScalaSignatureParser.java'
|
||||
scalaCompileOptions.additionalParameters = ['-sourcepath', file('src/main/scala').absolutePath]
|
||||
inputs.files(modernJavaSources).withPropertyName('modernJavaDeclarations').withPathSensitivity(PathSensitivity.RELATIVE)
|
||||
}
|
||||
|
||||
@@ -157,22 +157,18 @@ final class ScalaSignatureParser {
|
||||
Bytes bytes = entry.bytes();
|
||||
ByteCodeReader reader = bytes.reader();
|
||||
byte id = entry.id();
|
||||
switch (id) {
|
||||
case 1:
|
||||
case 2:
|
||||
return reader.readString(bytes.len());
|
||||
case 3:
|
||||
return sig.NoSymbol().full();
|
||||
case 9:
|
||||
case 10:
|
||||
return switch (id) {
|
||||
case 1, 2 -> reader.readString(bytes.len());
|
||||
case 3 -> sig.NoSymbol().full();
|
||||
case 9, 10 -> {
|
||||
String name = sig.evalS(reader.readNat());
|
||||
if (bytes.pos() + bytes.len() > reader.pos()) {
|
||||
name = sig.evalS(reader.readNat()) + "." + name;
|
||||
}
|
||||
return name;
|
||||
default:
|
||||
throw new MatchError(Byte.valueOf(id));
|
||||
}
|
||||
yield name;
|
||||
}
|
||||
default -> throw new MatchError(Byte.valueOf(id));
|
||||
};
|
||||
}
|
||||
|
||||
static List<?> evalList(ScalaSignature sig, ByteCodeReader reader) {
|
||||
@@ -185,61 +181,36 @@ final class ScalaSignatureParser {
|
||||
|
||||
static Object eval(ScalaSignature sig, int index, Object entry, ByteCodeReader reader, byte id) {
|
||||
// The Scala optimizer constructs case classes directly, without initializing their companions.
|
||||
switch (id) {
|
||||
case 1:
|
||||
case 2:
|
||||
return sig.evalS(index);
|
||||
case 3:
|
||||
return sig.NoSymbol();
|
||||
case 6:
|
||||
return sig.new ClassSymbol(sig.evalS(reader.readNat()), sig.evalT(reader.readNat()), reader.readNat(),
|
||||
reader.readNat());
|
||||
case 7:
|
||||
return sig.new ObjectSymbol(sig.evalS(reader.readNat()), sig.evalT(reader.readNat()), reader.readNat(),
|
||||
reader.readNat());
|
||||
case 8:
|
||||
return sig.new MethodSymbol(sig.evalS(reader.readNat()), sig.evalT(reader.readNat()), reader.readNat(),
|
||||
reader.readNat());
|
||||
case 9:
|
||||
case 10:
|
||||
return sig.new ExternalSymbol(sig.evalS(index));
|
||||
case 11:
|
||||
case 12: // NoPrefixType is treated as NoType in the reference.
|
||||
return sig.NoType();
|
||||
case 13:
|
||||
return sig.new ThisType(sig.evalT(reader.readNat()));
|
||||
case 14:
|
||||
return sig.new SingleType(sig.evalT(reader.readNat()), sig.evalT(reader.readNat()));
|
||||
case 21:
|
||||
case 48: // Retain the reference's parameterless interpretation of a bounded super type.
|
||||
return sig.new ParameterlessType(sig.evalT(reader.readNat()));
|
||||
case 25:
|
||||
return sig.new BooleanLiteral(reader.readLong() != 0);
|
||||
case 26:
|
||||
return sig.new ByteLiteral((byte) reader.readLong());
|
||||
case 27:
|
||||
return sig.new ShortLiteral((short) reader.readLong());
|
||||
case 28:
|
||||
return sig.new CharLiteral((char) reader.readLong());
|
||||
case 29:
|
||||
return sig.new IntLiteral((int) reader.readLong());
|
||||
case 30:
|
||||
return sig.new LongLiteral(reader.readLong());
|
||||
case 31:
|
||||
return sig.new FloatLiteral(Float.intBitsToFloat((int) reader.readLong()));
|
||||
case 32:
|
||||
return sig.new DoubleLiteral(Double.longBitsToDouble(reader.readLong()));
|
||||
case 33:
|
||||
return sig.new StringLiteral(sig.evalS(reader.readNat()));
|
||||
case 34:
|
||||
return sig.NullLiteral();
|
||||
case 35:
|
||||
return sig.new TypeLiteral(sig.evalT(reader.readNat()));
|
||||
case 36:
|
||||
return sig.new EnumLiteral(sig.evalT(reader.readNat()));
|
||||
default:
|
||||
return entry;
|
||||
}
|
||||
return switch (id) {
|
||||
case 1, 2 -> sig.evalS(index);
|
||||
case 3 -> sig.NoSymbol();
|
||||
case 6 -> sig.new ClassSymbol(sig.evalS(reader.readNat()), sig.evalT(reader.readNat()), reader.readNat(),
|
||||
reader.readNat());
|
||||
case 7 -> sig.new ObjectSymbol(sig.evalS(reader.readNat()), sig.evalT(reader.readNat()), reader.readNat(),
|
||||
reader.readNat());
|
||||
case 8 -> sig.new MethodSymbol(sig.evalS(reader.readNat()), sig.evalT(reader.readNat()), reader.readNat(),
|
||||
reader.readNat());
|
||||
case 9, 10 -> sig.new ExternalSymbol(sig.evalS(index));
|
||||
// NoPrefixType is treated as NoType in the reference.
|
||||
case 11, 12 -> sig.NoType();
|
||||
case 13 -> sig.new ThisType(sig.evalT(reader.readNat()));
|
||||
case 14 -> sig.new SingleType(sig.evalT(reader.readNat()), sig.evalT(reader.readNat()));
|
||||
// Retain the reference's parameterless interpretation of a bounded super type.
|
||||
case 21, 48 -> sig.new ParameterlessType(sig.evalT(reader.readNat()));
|
||||
case 25 -> sig.new BooleanLiteral(reader.readLong() != 0);
|
||||
case 26 -> sig.new ByteLiteral((byte) reader.readLong());
|
||||
case 27 -> sig.new ShortLiteral((short) reader.readLong());
|
||||
case 28 -> sig.new CharLiteral((char) reader.readLong());
|
||||
case 29 -> sig.new IntLiteral((int) reader.readLong());
|
||||
case 30 -> sig.new LongLiteral(reader.readLong());
|
||||
case 31 -> sig.new FloatLiteral(Float.intBitsToFloat((int) reader.readLong()));
|
||||
case 32 -> sig.new DoubleLiteral(Double.longBitsToDouble(reader.readLong()));
|
||||
case 33 -> sig.new StringLiteral(sig.evalS(reader.readNat()));
|
||||
case 34 -> sig.NullLiteral();
|
||||
case 35 -> sig.new TypeLiteral(sig.evalT(reader.readNat()));
|
||||
case 36 -> sig.new EnumLiteral(sig.evalT(reader.readNat()));
|
||||
default -> entry;
|
||||
};
|
||||
}
|
||||
|
||||
static <T> IndexedSeq<T> collect(ScalaSignature sig, int id) {
|
||||
|
||||
Reference in new issue
Block a user