naive codegen implementation
Some checks failed
Publish to snapshot maven / build (push) Failing after 1m15s

This commit is contained in:
lilly 2024-07-05 06:50:59 -05:00
parent 7023128e45
commit ba83b48e81
Signed by: MaeMachineBroke
GPG key ID: B54591A4805E9CC8
5 changed files with 109 additions and 0 deletions

View file

@ -0,0 +1,3 @@
dependencies {
implementation("net.bytebuddy:byte-buddy:1.14.17")
}

View file

@ -0,0 +1,66 @@
package dev.frogmc.froglib.gen.api;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.implementation.MethodCall;
import net.bytebuddy.matcher.ElementMatchers;
import net.minecraft.world.level.block.Block;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.ParameterizedType;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.function.Function;
/**
* {@code AbstractCodegenBuilder} is a template for creating Builder patterned classes that create anonymous, dynamic classes.
* @param <T> The superclass of the classes that will be generated.
*/
public abstract class AbstractCodegenBuilder<T> {
/**
* Represents the class builder.
*/
protected DynamicType.Builder<?> dt;
/**
* Represents the arguments that will be provided to the dynamic classes constructor.
*/
protected Object[] args; // TODO this seems bad?
/**
* Represents the fields that this dynamic class will contain.
*/
protected Map<String, Object> fields; // TODO this is really bad, probably just figure out how to actually properly add fields
/**
* Constructs a new AbstractCodegenBuilder. Subclasses should provide their own public constructor.
*/
protected AbstractCodegenBuilder() {
this.dt = new ByteBuddy()
.subclass((Class<T>) ((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[0]);
}
/**
* Overrides a method of the superclass in the dynamically-generated class.
* @param method The signature of the method to override.
* @param body A {@link FunctionalInterface} representing the body of the new overridden method.
*/
protected void overrideMethod(String method, Callable<?> body) throws NoSuchMethodException { // TODO handle instead of throwing
this.dt = this.dt.method(ElementMatchers.anyOf(((Class<T>) ((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[0]).getDeclaredMethod(method))) // FIXME i literally have no idea if this works lmao
.intercept(MethodCall.call(body));
}
/**
* Creates the dynamic class as well as a singleton instance of it. Subclasses should provide their own public {@code build} method.
* @return The singleton instance of the dynamic class.
*/
protected T build() throws InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { // TODO handle instead of throwing
if(this.fields.containsValue(null)) {
throw new IllegalAccessException();
}
return (T) this.dt
.make()
.load(getClass().getClassLoader())
.getLoaded() // TODO we might want to return this instead?
.getDeclaredConstructor()
.newInstance(this.args);
}
}

View file

@ -0,0 +1,22 @@
[frog]
format_version = "1.0.0"
[frog.mod]
id = "froglib_gen"
name = "FrogLib Data and Code Generation"
version = "$version"
license = "Apache-2.0"
credits = [
{ name = "FrogMC Team", roles = ["author"] }
]
[frog.dependencies]
depends = [
{ id = "minecraft", versions = "~$game_version", name = "Minecraft" }
]
[frog.extensions]
prelaunch = "net.frogmc.froglib.gen.impl.FrogGenPrelaunch"
mixin = [
"froglib.gen.mixins.json"
]

View file

@ -0,0 +1,16 @@
{
"required": true,
"minVersion": "0.8",
"package": "dev.frogmc.froglib.gen.impl.mixin",
"compatibilityLevel": "JAVA_21",
"mixins": [
],
"server": [
],
"client": [
],
"injectors": {
"defaultRequire": 1
}
}

View file

@ -27,3 +27,5 @@ include("library:registries")
findProject(":library:registries")?.name = "registries"
include("library:player")
findProject(":library:player")?.name = "player"
include("library:gen")
findProject(":library:gen")?.name = "gen"