commit bce3396cf5af9474add171ac548717efb101b621
Author: Parker TenBroeck <51721964+ParkerTenBroeck@users.noreply.github.com>
Date: Thu Apr 3 00:22:50 2025 -0400
first
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..e80d5dc
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,31 @@
+### IntelliJ IDEA ###
+out/
+!**/src/main/**/out/
+!**/src/test/**/out/
+
+### Eclipse ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+bin/
+!**/src/main/**/bin/
+!**/src/test/**/bin/
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+
+### VS Code ###
+.vscode/
+
+### Mac OS ###
+.DS_Store
+
+*.iml
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..26d3352
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..454992c
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..0033e36
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..94a25f7
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Main.java b/src/Main.java
new file mode 100644
index 0000000..d5238c9
--- /dev/null
+++ b/src/Main.java
@@ -0,0 +1,5 @@
+public class Main {
+ public static void main(String[] args) {
+ System.out.println("Hello, World!");
+ }
+}
\ No newline at end of file
diff --git a/src/generator/Fun.java b/src/generator/Fun.java
new file mode 100644
index 0000000..c3f3829
--- /dev/null
+++ b/src/generator/Fun.java
@@ -0,0 +1,468 @@
+package generator;
+
+
+import java.io.IOException;
+import java.io.PrintStream;
+import java.lang.classfile.*;
+import java.lang.classfile.attribute.StackMapFrameInfo;
+import java.lang.classfile.instruction.*;
+import java.lang.constant.ClassDesc;
+import java.lang.constant.ConstantDescs;
+import java.lang.constant.MethodTypeDesc;
+import java.lang.reflect.AccessFlag;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Objects;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import static java.lang.classfile.attribute.StackMapFrameInfo.SimpleVerificationTypeInfo.TOP;
+
+public class Fun {
+ public static void main(String... args) throws Exception {
+// var loader = new GeneratorClassLoader(Fun.class.getClassLoader());
+// loader.loadClass(Fun.class.getName()).getMethod("run").invoke(null);
+ var thread = new Thread(() -> {
+ Fun.run();
+ });
+ thread.setContextClassLoader(new GeneratorClassLoader(Fun.class.getClassLoader()));
+ thread.start();
+ }
+
+ public static void run() {
+ {
+ var gen = Test.test(new double[]{1,2,3,45,6,4,3,3,452,452,45,345,45});
+ while (gen.next() instanceof Gen.Yield(var val)) {
+ System.out.println(val);
+ }
+ }
+
+ var gen = Test.parse("f7(x,y,z,w, u,v, othersIg) = v-(x*y+y+ln(z)^2*sin(z*pi/2))/(w*u)+sqrt(othersIg*120e-1)");
+ var res = gen.next();
+ while (true) {
+ System.out.println(res);
+ if (res instanceof Gen.Ret || res == null) break;
+ res = gen.next();
+ }
+ }
+
+ public static class GeneratorClassLoader extends ClassLoader {
+ private final static MethodTypeDesc MTD_void_String = MethodTypeDesc.of(ConstantDescs.CD_void, ConstantDescs.CD_String);
+ private final static ClassDesc CD_System = ClassDesc.ofDescriptor(System.class.descriptorString());
+ private final static ClassDesc CD_PrintStream = ClassDesc.ofDescriptor(PrintStream.class.descriptorString());
+
+ private final static ClassDesc CD_Gen = ClassDesc.ofDescriptor(Gen.class.descriptorString());
+ private final static ClassDesc CD_Res = ClassDesc.ofDescriptor(Gen.Res.class.descriptorString());
+ private final static ClassDesc CD_Yield = ClassDesc.ofDescriptor(Gen.Yield.class.descriptorString());
+ private final static ClassDesc CD_Ret = ClassDesc.ofDescriptor(Gen.Ret.class.descriptorString());
+ private final static MethodTypeDesc MTD_Res = MethodTypeDesc.of(CD_Res);
+ private final static MethodTypeDesc MTD_Gen_Obj = MethodTypeDesc.of(CD_Gen, ConstantDescs.CD_Object);
+
+ private final HashMap customClazzDefMap = new HashMap<>();
+ private final HashMap> customClazzMap = new HashMap<>();
+
+ public GeneratorClassLoader(ClassLoader parent) {
+ super(parent);
+ }
+
+ @Override
+ public Class> loadClass(String name) throws ClassNotFoundException {
+ if (customClazzDefMap.get(name) instanceof byte[] bytes)
+ customClazzMap.put(name, defineClass(name, bytes, 0, bytes.length));
+ if (customClazzMap.get(name) instanceof Class> clazz)
+ return clazz;
+ if (name.startsWith("java"))
+ return super.loadClass(name);
+
+ var p = "/" + name.replace('.', '/') + ".class";
+ try (var stream = Fun.class.getResourceAsStream(p)) {
+ var bytes = Objects.requireNonNull(stream).readAllBytes();
+ bytes = searchForGenerators(bytes);
+ Files.write(Path.of("cs/" + name + ".class"), bytes);
+ customClazzDefMap.put(name, bytes);
+ customClazzMap.put(name, defineClass(name, bytes, 0, bytes.length));
+ return customClazzMap.get(name);
+ } catch (IOException e) {
+ throw new ClassNotFoundException(name, e);
+ }
+ }
+
+ public byte[] searchForGenerators(byte[] in) {
+ var clm = ClassFile.of().parse(in);
+ return ClassFile.of().build(clm.thisClass().asSymbol(), cb -> {
+ for (var ce : clm) {
+ var isGen = clm.thisClass().asSymbol().descriptorString().equals(Gen.class.descriptorString());
+ if (ce instanceof MethodModel mem && !isGen) {
+ var methodRetGen = mem.methodTypeSymbol().returnType().descriptorString().equals(Gen.class.descriptorString());
+ if (methodRetGen) {
+ cb.withMethod(mem.methodName().stringValue(), mem.methodTypeSymbol(), mem.flags().flagsMask(), mb -> {
+ for (var me : mem) {
+ if (me instanceof CodeModel com) {
+ mb.withCode(cob -> rebuildGeneratorMethod(clm, mem, com, cob));
+ } else mb.with(me);
+ }
+ });
+ } else
+ cb.with(mem);
+
+
+ } else cb.with(ce);
+ }
+ });
+ }
+
+ private ClassDesc generateGeneratorFromGenMethod(ClassModel clm, MethodModel mem, CodeModel com, CodeBuilder scob) {
+ var cd = ClassDesc.of("Gen" + customClazzDefMap.size());
+
+ var bytes = ClassFile.of(ClassFile.StackMapsOption.STACK_MAPS_WHEN_REQUIRED).build(cd, clb -> {
+
+ clb.withInterfaces(List.of(clb.constantPool().classEntry(CD_Gen)));
+
+ scob.new_(cd).dup();
+ var mts = mem.methodTypeSymbol();
+ mts = mts.changeReturnType(ConstantDescs.CD_void);
+ if (!mem.flags().has(AccessFlag.STATIC)) {
+ mts = mts.insertParameterTypes(0, clm.thisClass().asSymbol());
+ }
+
+ int offset = 0;
+ var mts_params = mts.parameterArray();
+ for (var param : mts_params) {
+ clb.withField("param_" + offset, param, ClassFile.ACC_PRIVATE);
+ var tk = TypeKind.fromDescriptor(param.descriptorString());
+ scob.loadLocal(tk, offset);
+ offset += tk.slotSize();
+ }
+ var count = offset;
+ scob.invokespecial(cd, ConstantDescs.INIT_NAME, mts).areturn();
+
+
+ clb.withMethod(ConstantDescs.INIT_NAME, mts, ClassFile.ACC_PUBLIC,
+ mb -> mb.withCode(cob -> {
+ cob.aload(0).invokespecial(ConstantDescs.CD_Object, ConstantDescs.INIT_NAME, ConstantDescs.MTD_void);
+ int offset2 = 0;
+ for (var param : mts_params) {
+ var tk = TypeKind.fromDescriptor(param.descriptorString());
+ cob.aload(0).loadLocal(tk, offset2 + 1).putfield(cd, "param_" + offset2, param);
+ offset2 += tk.slotSize();
+ }
+ cob.return_();
+ })
+ );
+ clb.withMethod("next", MTD_Res, ClassFile.ACC_PUBLIC, mb -> {
+ mb.withCode(cob -> cob.trying(
+ tcob -> {
+ generateStateMachine(mts_params, cd, clb, com, tcob, count);
+ },
+ ctb -> ctb.catchingAll(
+ blc -> blc.aload(0).loadConstant(-1).putfield(cd, "___state___", TypeKind.INT.upperBound()).athrow()
+ )
+ ).aconst_null().areturn()
+ );
+ });
+ }
+ );
+ try {
+ Files.write(Path.of("cs/" + cd.displayName() + ".class"), bytes);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ customClazzDefMap.put(cd.displayName(), bytes);
+ return cd;
+ }
+
+ private static class LocalTracker{
+
+ record LocalStore(String name, ClassDesc cd){}
+
+ HashMap parameter_map = new HashMap<>();
+
+ HashMap localVarTypes = new HashMap<>();
+ HashMap localVarDetailedType = new HashMap<>();
+ HashMap