diff --git a/app/build.gradle.kts b/app/build.gradle.kts index a8c2b52..d44ea18 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -16,6 +16,21 @@ java { } } -application { - mainClass = "demo.Main" +tasks.withType { + options.compilerArgs.add("--enable-preview") } + +tasks.register("lexer"){ + javaLauncher.set(javaToolchains.launcherFor(java.toolchain)) + jvmArgs("--enable-preview") + group = "Demos" + mainClass = "lexer.Main" + classpath = sourceSets["main"].runtimeClasspath +} + +tasks.register("sockets"){ + javaLauncher.set(javaToolchains.launcherFor(java.toolchain)) + group = "Demos" + mainClass = "sockets.Main" + classpath = sourceSets["main"].runtimeClasspath +} \ No newline at end of file diff --git a/app/src/main/java/demo/AsyncExamples.java b/app/src/main/java/demo/AsyncExamples.java deleted file mode 100644 index e0e4123..0000000 --- a/app/src/main/java/demo/AsyncExamples.java +++ /dev/null @@ -1,67 +0,0 @@ -package demo; - -import com.parkertenbroeck.async_runtime.Jokio; -import com.parkertenbroeck.async_runtime.io.net.ServerSocket; -import com.parkertenbroeck.async_runtime.io.net.Socket; -import com.parkertenbroeck.future.Future; -import com.parkertenbroeck.generators.loadtime.future.Cancellation; - -import java.io.IOException; -import java.net.InetSocketAddress; -import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; - -public class AsyncExamples { - - public static Future run() throws IOException { - Jokio.runtime().await().spawn(server()); - for(int i = 0; i < 50; i ++){ - var builder = new StringBuilder(); - for(int c = 0; c < 4096; c ++) - builder.append((char)((Math.random()*('z'-'a')+'a'))); - Jokio.runtime().await().spawn(verify_echo(builder.toString())); - } - Runnable meow = () -> { - System.out.println(); - }; - meow.run(); - - return Future.ret(); - } - - public static Future server() throws IOException { - try(@Cancellation("close") var ss = ServerSocket.bind(new InetSocketAddress("0.0.0.0", 42069))){ - while (true){ - Jokio.runtime().await().spawn(echo(ss.accept().await())); - } - } - } - - public static Future echo(@Cancellation("close") Socket socket) throws IOException{ - try(socket){ - var buffer = ByteBuffer.allocate(4096); - while(true){ - socket.read(buffer).await(); - buffer.flip(); - socket.write_all(buffer).await(); - buffer.clear(); - } - } - } - - public static Future verify_echo(String message) throws IOException { - byte[] msg_bytes = message.getBytes(StandardCharsets.UTF_8); - try(@Cancellation("close") var socket = Socket.connect(new InetSocketAddress("localhost", 42069)).await()){ - var buffer = ByteBuffer.allocate(message.length()); - while(true){ - buffer.limit(message.length()).put(msg_bytes).position(0); - var wrote = socket.write_all(buffer).await(); - buffer.clear().limit(wrote); - socket.read_all(buffer).await(); - if(!buffer.position(0).equals(ByteBuffer.wrap(msg_bytes))) - throw new RuntimeException(); - buffer.clear(); - } - } - } -} diff --git a/app/src/main/java/demo/Lexer.java b/app/src/main/java/demo/Lexer.java deleted file mode 100644 index 9475d50..0000000 --- a/app/src/main/java/demo/Lexer.java +++ /dev/null @@ -1,69 +0,0 @@ -package demo; - -import com.parkertenbroeck.gen.Gen; - -public class Lexer { - public sealed interface Token{} - public enum Punc implements Token { - LPar, - RPar, - Add, - Sub, - Div, - Mul, - Equals, - Carrot, - Comma - } - - public record Ident(String ident) implements Token {} - public record Numeric(double val) implements Token {} - - public static Gen parse(String input) { - int start; - int pos = 0; - while(true){ - if (input.length() <= pos) - return Gen.ret(); - start = pos; - char curr = input.charAt(pos++); - - switch (curr){ - case '(' -> Gen.yield(Punc.LPar); - case ')' -> Gen.yield(Punc.RPar); - case '+' -> Gen.yield(Punc.Add); - case '-' -> Gen.yield(Punc.Sub); - case '/' -> Gen.yield(Punc.Div); - case '*' -> Gen.yield(Punc.Mul); - case ',' -> Gen.yield(Punc.Comma); - case '^' -> Gen.yield(Punc.Carrot); - case '=' -> Gen.yield(Punc.Equals); -// case Character c when Character.isWhitespace(c) -> {} -// case Character c when Character.isAlphabetic(c) -> { -// while((Character.isLetter(curr) || Character.isLetterOrDigit(curr))){ -// if(pos>=input.length())break; -// curr = input.charAt(pos++); -// } -// Gen.yield(new Ident(input.substring(start, pos-1))); -// } -// case Character c when '0' <= c && c <= '9' -> { -// boolean exp = false; -// while(('0' <= curr && curr <= '9') || curr == '_' || curr == '.'){ -// if(pos>=input.length())break; -// curr = input.charAt(pos++); -// if(curr=='e'||curr=='E'){ -// if(exp) throw new RuntimeException("Exponent Already included"); -// exp = true; -// if(pos+2>=input.length()) -// throw new RuntimeException("Expected another character after exponent"); -// curr = input.charAt(++pos); pos++; -// } -// } -// -// Gen.yield(new Numeric(Double.parseDouble(input.substring(start, pos-1).replace("_", "")))); -// } - default -> throw new RuntimeException("Invalid char " + curr); - } - } - } -} diff --git a/app/src/main/java/demo/Main.java b/app/src/main/java/demo/Main.java deleted file mode 100644 index a35a75e..0000000 --- a/app/src/main/java/demo/Main.java +++ /dev/null @@ -1,66 +0,0 @@ -package demo; - -import com.parkertenbroeck.async_runtime.Jokio; -import com.parkertenbroeck.async_runtime.io.fs.File; -import com.parkertenbroeck.generators.RT; -import com.parkertenbroeck.future.Future; -import com.parkertenbroeck.gen.Gen; -import com.parkertenbroeck.generators.loadtime.future.Cancellation; - -import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.file.Path; -import java.util.function.Function; -import java.util.function.Supplier; - -public class Main implements Runnable { - public static void main(String[] args) { - RT.runWithGeneratorSupport(Main.class); - } - - @Override - public void run() { -// lexer(); - await(); -// try { -// System.out.println(new Jokio().blocking(files())); -// } catch (IOException ignore) {} - } -// -// static Future files() throws IOException{ -// try(@Cancellation("close") var file = File.open(Path.of("./src/Main.java"))){ -// var buf = ByteBuffer.allocate((int) file.size()); -// var read = file.read_all(buf).await(); -// return Future.ret(new String(buf.array(), 0, read)); -// } -// } -// -// T async_lambda(Supplier> lambda) throws E{ -// return new Jokio().blocking(lambda.get()); -// } -// -// - private static int nya = 0; -class Meow{ - void test(){ - nya = 2; - } -} - void await(){ - - new Meow().test(); - try{ - new Jokio().blocking(AsyncExamples.run()); - }catch (Exception e){ - throw new RuntimeException(e); - } - } -// -// -// void lexer(){ -// var gen = Lexer.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)"); -// while(gen.next() instanceof Gen.Yield(var tok)) { -// System.out.println(tok); -// } -// } -} \ No newline at end of file diff --git a/app/src/main/java/lexer/Lexer.java b/app/src/main/java/lexer/Lexer.java new file mode 100644 index 0000000..4458d0b --- /dev/null +++ b/app/src/main/java/lexer/Lexer.java @@ -0,0 +1,69 @@ +package lexer; + +import com.parkertenbroeck.generator.Gen; + +public class Lexer { + public sealed interface Token{} + public enum Punc implements Token { + LPar, + RPar, + Add, + Sub, + Div, + Mul, + Equals, + Carrot, + Comma + } + + public record Ident(String ident) implements Token {} + public record Numeric(double val) implements Token {} + + public static Gen parse(String input) { + int start; + int pos = 0; + while(true){ + if (input.length() <= pos) + return Gen.ret(); + start = pos; + char curr = input.charAt(pos++); + + switch (curr){ + case '(' -> Gen.yield(Punc.LPar); + case ')' -> Gen.yield(Punc.RPar); + case '+' -> Gen.yield(Punc.Add); + case '-' -> Gen.yield(Punc.Sub); + case '/' -> Gen.yield(Punc.Div); + case '*' -> Gen.yield(Punc.Mul); + case ',' -> Gen.yield(Punc.Comma); + case '^' -> Gen.yield(Punc.Carrot); + case '=' -> Gen.yield(Punc.Equals); + case char c when Character.isWhitespace(c) -> {} + case char c when Character.isAlphabetic(c) -> { + while((Character.isLetter(curr) || Character.isLetterOrDigit(curr))){ + if(pos>=input.length())break; + curr = input.charAt(pos++); + } + Gen.yield(new Ident(input.substring(start, pos-1))); + } + case char c when '0' <= c && c <= '9' -> { + boolean exp = false; + while(('0' <= curr && curr <= '9') || curr == '_' || curr == '.'){ + if(pos>=input.length())break; + curr = input.charAt(pos++); + if(curr=='e'||curr=='E'){ + if(exp) throw new RuntimeException("Exponent Already included"); + exp = true; + if(pos+2>=input.length()) + throw new RuntimeException("Expected another character after exponent"); + curr = input.charAt(++pos); pos++; + } + } + + Gen.yield(new Numeric(Double.parseDouble(input.substring(start, pos-1).replace("_", "")))); + } + default -> throw new RuntimeException("Invalid char " + curr); + } + } + } +} diff --git a/app/src/main/java/lexer/Main.java b/app/src/main/java/lexer/Main.java new file mode 100644 index 0000000..dd5631b --- /dev/null +++ b/app/src/main/java/lexer/Main.java @@ -0,0 +1,20 @@ +package lexer; + +import com.parkertenbroeck.generator.Gen; +import com.parkertenbroeck.bcms.RT; +import com.parkertenbroeck.bcms.loadtime.StateMachineClassLoader; + +public class Main { + public static void main(String[] args) { + RT.runWithStateMachines(StateMachineClassLoader.Config.builtin(), (Object) args); + + lexer(); + } + + static void lexer(){ + var gen = Lexer.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)"); + while(gen.next() instanceof Gen.Yield(var tok)) { + System.out.println(tok); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/sockets/Main.java b/app/src/main/java/sockets/Main.java new file mode 100644 index 0000000..ed20c2c --- /dev/null +++ b/app/src/main/java/sockets/Main.java @@ -0,0 +1,21 @@ +package sockets; + +import com.parkertenbroeck.async_runtime.Jokio; +import com.parkertenbroeck.bcms.RT; +import com.parkertenbroeck.bcms.loadtime.StateMachineClassLoader; + +public class Main { + public static void main(String[] args) { + RT.runWithStateMachines(StateMachineClassLoader.Config.builtin(), (Object) args); + + await(); + } + + static void await(){ + try{ + new Jokio().blocking(Sockets.run()); + }catch (Exception e){ + throw new RuntimeException(e); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/sockets/Sockets.java b/app/src/main/java/sockets/Sockets.java new file mode 100644 index 0000000..4e75f6e --- /dev/null +++ b/app/src/main/java/sockets/Sockets.java @@ -0,0 +1,87 @@ +package sockets; + +import com.parkertenbroeck.async_runtime.Delay; +import com.parkertenbroeck.async_runtime.Jokio; +import com.parkertenbroeck.async_runtime.io.net.ServerSocket; +import com.parkertenbroeck.async_runtime.io.net.Socket; +import com.parkertenbroeck.future.Future; +import com.parkertenbroeck.bcms.loadtime.future.Cancellation; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; + +public class Sockets { + + private static long bytes_sent = 0; + private static long bytes_received = 0; + + public static Future run() throws IOException { + Jokio.runtime().await().spawn(server()); + for(int i = 0; i < 50; i ++){ + var builder = new StringBuilder(); + for(int c = 0; c < 4096*2; c ++) + builder.append((char)((Math.random()*('z'-'a')+'a'))); + Jokio.runtime().await().spawn(verify_echo(builder.toString())); + } + + stats().await(); + return Future.ret(); + } + + public static Future stats() { + long start = System.currentTimeMillis(); + long start_s = bytes_sent; + long start_r = bytes_received; + while(true){ + Delay.delay(1000).await(); + long end = System.currentTimeMillis(); + var duration = (end-start)/1000.0; + start = end; + System.out.format("sent: % 10d B\treceived: % 10d B\tduration: % 2.3fs\n", bytes_sent, bytes_received, duration); + System.out.format("sent: % 2.5f Gib/s\treceived: % 2.5f Gib/s\n", (bytes_sent-start_s)/duration*7.4505805969238E-9, (bytes_received-start_r)/duration*7.4505805969238E-9); + start_s = bytes_sent; + start_r = bytes_received; + } + } + + public static Future server() throws IOException { + try(@Cancellation("close") var ss = ServerSocket.bind(new InetSocketAddress("0.0.0.0", 42069))){ + while (true){ + Jokio.runtime().await().spawn(echo(ss.accept().await())); + } + } + } + + public static Future echo(@Cancellation("close") Socket socket) throws IOException{ + try(socket){ + var buffer = ByteBuffer.allocate(4096*2); + while(true){ + bytes_received = socket.read(buffer).await() + bytes_received; + buffer.flip(); + bytes_sent = socket.write_all(buffer).await() + bytes_sent; + buffer.clear().limit(buffer.capacity()); + } + } + } + + public static Future verify_echo(String message) throws IOException { + byte[] msg_bytes = message.getBytes(StandardCharsets.UTF_8); + ByteBuffer msg_cmp_buffer = ByteBuffer.wrap(msg_bytes); + + var buffer = ByteBuffer.allocate(message.length()); + buffer.put(msg_bytes).limit(msg_bytes.length).position(0); + + try(@Cancellation("close") var socket = Socket.connect(new InetSocketAddress("localhost", 42069)).await()){ + while(true){ + bytes_sent = socket.write_all(buffer).await() + bytes_sent; + buffer.flip(); + bytes_received = socket.read_all(buffer).await() + bytes_received; + buffer.flip(); + if(!buffer.equals(msg_cmp_buffer)) + throw new RuntimeException(); + } + } + } +} diff --git a/lib/build.gradle.kts b/lib/build.gradle.kts index 4a94a01..74f2d3a 100644 --- a/lib/build.gradle.kts +++ b/lib/build.gradle.kts @@ -1,3 +1,5 @@ +version = "0.1.0" + plugins { `java-library` } @@ -12,6 +14,7 @@ dependencies { testRuntimeOnly("org.junit.platform:junit-platform-launcher") } + java { toolchain { languageVersion = JavaLanguageVersion.of(24) @@ -21,4 +24,4 @@ java { tasks.named("test") { // Use JUnit Platform for unit tests. useJUnitPlatform() -} +} \ No newline at end of file diff --git a/lib/src/main/java/com/parkertenbroeck/async_runtime/io/net/Socket.java b/lib/src/main/java/com/parkertenbroeck/async_runtime/io/net/Socket.java index acc7545..ed34365 100644 --- a/lib/src/main/java/com/parkertenbroeck/async_runtime/io/net/Socket.java +++ b/lib/src/main/java/com/parkertenbroeck/async_runtime/io/net/Socket.java @@ -92,7 +92,7 @@ public class Socket implements AutoCloseable, Readable, Writable write_all(ByteBuffer buffer){ var wrote = buffer.remaining(); return waker -> { - socket.write(buffer); + var nya = socket.write(buffer); if(!buffer.hasRemaining()) return wrote; SELECTOR.register(socket, SelectionKey.OP_WRITE, waker); return Future.Pending.INSTANCE; @@ -103,6 +103,7 @@ public class Socket implements AutoCloseable, Readable, Writable read(ByteBuffer buffer){ return waker -> { var read = socket.read(buffer); + if(read == -1)throw new IOException("Reached end of stream"); if(read!=0) return read; SELECTOR.register(socket, SelectionKey.OP_READ, waker); return Future.Pending.INSTANCE; diff --git a/lib/src/main/java/com/parkertenbroeck/bcms/RT.java b/lib/src/main/java/com/parkertenbroeck/bcms/RT.java new file mode 100644 index 0000000..a80904e --- /dev/null +++ b/lib/src/main/java/com/parkertenbroeck/bcms/RT.java @@ -0,0 +1,31 @@ +package com.parkertenbroeck.bcms; + + +import com.parkertenbroeck.bcms.loadtime.StateMachineClassLoader; + +import java.lang.reflect.Modifier; +import java.util.Set; + +import static java.lang.StackWalker.Option.*; + +public class RT { + public static void runWithStateMachines(StateMachineClassLoader.Config config, Object... params){ + if(RT.class.getClassLoader() instanceof StateMachineClassLoader)return; + + var loader = new StateMachineClassLoader(RT.class.getClassLoader(), config); + try{ + StackWalker walker = StackWalker.getInstance(Set.of(RETAIN_CLASS_REFERENCE, SHOW_REFLECT_FRAMES, SHOW_HIDDEN_FRAMES)); + var frame = walker.walk(s -> s.skip(1).findFirst()).get(); + var clazzL = loader.loadClass(frame.getClassName()); + var method = clazzL.getDeclaredMethod(frame.getMethodName(), frame.getMethodType().parameterArray()); + if((method.getModifiers() & Modifier.STATIC) == 0){ + method.invoke(clazzL.getConstructor().newInstance(), params); + }else{ + method.invoke(null, params); + } + System.exit(0); + }catch (Exception e){ + throw new RuntimeException(e); + } + } +} diff --git a/lib/src/main/java/com/parkertenbroeck/generators/loadtime/Frame.java b/lib/src/main/java/com/parkertenbroeck/bcms/loadtime/Frame.java similarity index 97% rename from lib/src/main/java/com/parkertenbroeck/generators/loadtime/Frame.java rename to lib/src/main/java/com/parkertenbroeck/bcms/loadtime/Frame.java index ba07863..aa60ea5 100644 --- a/lib/src/main/java/com/parkertenbroeck/generators/loadtime/Frame.java +++ b/lib/src/main/java/com/parkertenbroeck/bcms/loadtime/Frame.java @@ -1,4 +1,4 @@ -package com.parkertenbroeck.generators.loadtime; +package com.parkertenbroeck.bcms.loadtime; import java.lang.classfile.CodeBuilder; import java.lang.classfile.instruction.LineNumber; diff --git a/lib/src/main/java/com/parkertenbroeck/generators/loadtime/FrameTracker.java b/lib/src/main/java/com/parkertenbroeck/bcms/loadtime/FrameTracker.java similarity index 97% rename from lib/src/main/java/com/parkertenbroeck/generators/loadtime/FrameTracker.java rename to lib/src/main/java/com/parkertenbroeck/bcms/loadtime/FrameTracker.java index 7f390e7..52acae5 100644 --- a/lib/src/main/java/com/parkertenbroeck/generators/loadtime/FrameTracker.java +++ b/lib/src/main/java/com/parkertenbroeck/bcms/loadtime/FrameTracker.java @@ -1,4 +1,4 @@ -package com.parkertenbroeck.generators.loadtime; +package com.parkertenbroeck.bcms.loadtime; import java.lang.classfile.*; @@ -30,7 +30,7 @@ public class FrameTracker { ITEM_LONG_2ND = 13, ITEM_DOUBLE_2ND = 14; - public static ArrayList frames(StateMachineBuilder smb, CodeModel src_com) { + public static ArrayList frames(StateMachineBuilder smb, CodeModel src_com) { var ft = new FrameTracker(smb, src_com); var frames = new ArrayList(); for(var coe : src_com){ @@ -496,6 +496,16 @@ public class FrameTracker { } } + private void pushFromStackMapFrame(List list, Type type){ + list.add(type); + if(type.tag() == Type.LONG_TYPE.tag()){ + list.add(Type.LONG2_TYPE); + } + if(type.tag() == Type.DOUBLE2_TYPE.tag()){ + list.add(Type.DOUBLE2_TYPE); + } + } + public void encounterLabel(Label l) { if(annotationStartMap.get(l) instanceof ArrayList list) activeAnnotations.addAll(list); @@ -507,11 +517,11 @@ public class FrameTracker { if (tmp != null) { stack.clear(); locals.clear(); - for( var sl : tmp.stack()) - pushStack(Type.verificationType(sl, this)); + for(var sl : tmp.stack()) + pushFromStackMapFrame(stack, Type.verificationType(sl, this)); - for( var sl : tmp.locals()) - locals.add(Type.verificationType(sl, this)); + for(var lv : tmp.locals()) + pushFromStackMapFrame(locals, Type.verificationType(lv, this)); } } } diff --git a/lib/src/main/java/com/parkertenbroeck/generators/loadtime/ParamConsumer.java b/lib/src/main/java/com/parkertenbroeck/bcms/loadtime/ParamConsumer.java similarity index 72% rename from lib/src/main/java/com/parkertenbroeck/generators/loadtime/ParamConsumer.java rename to lib/src/main/java/com/parkertenbroeck/bcms/loadtime/ParamConsumer.java index e7b23b0..171f573 100644 --- a/lib/src/main/java/com/parkertenbroeck/generators/loadtime/ParamConsumer.java +++ b/lib/src/main/java/com/parkertenbroeck/bcms/loadtime/ParamConsumer.java @@ -1,4 +1,4 @@ -package com.parkertenbroeck.generators.loadtime; +package com.parkertenbroeck.bcms.loadtime; import java.lang.constant.ClassDesc; diff --git a/lib/src/main/java/com/parkertenbroeck/generators/loadtime/ReplacementKind.java b/lib/src/main/java/com/parkertenbroeck/bcms/loadtime/ReplacementKind.java similarity index 67% rename from lib/src/main/java/com/parkertenbroeck/generators/loadtime/ReplacementKind.java rename to lib/src/main/java/com/parkertenbroeck/bcms/loadtime/ReplacementKind.java index 3d7e38a..6c0f101 100644 --- a/lib/src/main/java/com/parkertenbroeck/generators/loadtime/ReplacementKind.java +++ b/lib/src/main/java/com/parkertenbroeck/bcms/loadtime/ReplacementKind.java @@ -1,4 +1,4 @@ -package com.parkertenbroeck.generators.loadtime; +package com.parkertenbroeck.bcms.loadtime; public enum ReplacementKind { ImmediateReplacingPop, diff --git a/lib/src/main/java/com/parkertenbroeck/generators/loadtime/SavedStateTracker.java b/lib/src/main/java/com/parkertenbroeck/bcms/loadtime/SavedStateTracker.java similarity index 98% rename from lib/src/main/java/com/parkertenbroeck/generators/loadtime/SavedStateTracker.java rename to lib/src/main/java/com/parkertenbroeck/bcms/loadtime/SavedStateTracker.java index 5d1f09f..83668af 100644 --- a/lib/src/main/java/com/parkertenbroeck/generators/loadtime/SavedStateTracker.java +++ b/lib/src/main/java/com/parkertenbroeck/bcms/loadtime/SavedStateTracker.java @@ -1,4 +1,4 @@ -package com.parkertenbroeck.generators.loadtime; +package com.parkertenbroeck.bcms.loadtime; import java.lang.classfile.CodeBuilder; import java.lang.classfile.TypeKind; diff --git a/lib/src/main/java/com/parkertenbroeck/generators/loadtime/SpecialMethod.java b/lib/src/main/java/com/parkertenbroeck/bcms/loadtime/SpecialMethod.java similarity index 76% rename from lib/src/main/java/com/parkertenbroeck/generators/loadtime/SpecialMethod.java rename to lib/src/main/java/com/parkertenbroeck/bcms/loadtime/SpecialMethod.java index 6f56755..4df55dc 100644 --- a/lib/src/main/java/com/parkertenbroeck/generators/loadtime/SpecialMethod.java +++ b/lib/src/main/java/com/parkertenbroeck/bcms/loadtime/SpecialMethod.java @@ -1,4 +1,4 @@ -package com.parkertenbroeck.generators.loadtime; +package com.parkertenbroeck.bcms.loadtime; import java.lang.constant.ClassDesc; import java.lang.constant.MethodTypeDesc; diff --git a/lib/src/main/java/com/parkertenbroeck/generators/loadtime/SpecialMethodBuilder.java b/lib/src/main/java/com/parkertenbroeck/bcms/loadtime/SpecialMethodBuilder.java similarity index 80% rename from lib/src/main/java/com/parkertenbroeck/generators/loadtime/SpecialMethodBuilder.java rename to lib/src/main/java/com/parkertenbroeck/bcms/loadtime/SpecialMethodBuilder.java index 5e3ea1b..f5446ea 100644 --- a/lib/src/main/java/com/parkertenbroeck/generators/loadtime/SpecialMethodBuilder.java +++ b/lib/src/main/java/com/parkertenbroeck/bcms/loadtime/SpecialMethodBuilder.java @@ -1,4 +1,4 @@ -package com.parkertenbroeck.generators.loadtime; +package com.parkertenbroeck.bcms.loadtime; import java.lang.classfile.CodeBuilder; diff --git a/lib/src/main/java/com/parkertenbroeck/generators/loadtime/SpecialMethodHandler.java b/lib/src/main/java/com/parkertenbroeck/bcms/loadtime/SpecialMethodHandler.java similarity index 87% rename from lib/src/main/java/com/parkertenbroeck/generators/loadtime/SpecialMethodHandler.java rename to lib/src/main/java/com/parkertenbroeck/bcms/loadtime/SpecialMethodHandler.java index bd63039..ba523d8 100644 --- a/lib/src/main/java/com/parkertenbroeck/generators/loadtime/SpecialMethodHandler.java +++ b/lib/src/main/java/com/parkertenbroeck/bcms/loadtime/SpecialMethodHandler.java @@ -1,4 +1,4 @@ -package com.parkertenbroeck.generators.loadtime; +package com.parkertenbroeck.bcms.loadtime; import java.lang.classfile.CodeBuilder; diff --git a/lib/src/main/java/com/parkertenbroeck/generators/loadtime/StateBuilder.java b/lib/src/main/java/com/parkertenbroeck/bcms/loadtime/StateBuilder.java similarity index 95% rename from lib/src/main/java/com/parkertenbroeck/generators/loadtime/StateBuilder.java rename to lib/src/main/java/com/parkertenbroeck/bcms/loadtime/StateBuilder.java index 539188f..afb91c0 100644 --- a/lib/src/main/java/com/parkertenbroeck/generators/loadtime/StateBuilder.java +++ b/lib/src/main/java/com/parkertenbroeck/bcms/loadtime/StateBuilder.java @@ -1,4 +1,4 @@ -package com.parkertenbroeck.generators.loadtime; +package com.parkertenbroeck.bcms.loadtime; import java.lang.classfile.CodeBuilder; import java.lang.classfile.Label; diff --git a/lib/src/main/java/com/parkertenbroeck/generators/loadtime/StateMachineBuilder.java b/lib/src/main/java/com/parkertenbroeck/bcms/loadtime/StateMachineBuilder.java similarity index 97% rename from lib/src/main/java/com/parkertenbroeck/generators/loadtime/StateMachineBuilder.java rename to lib/src/main/java/com/parkertenbroeck/bcms/loadtime/StateMachineBuilder.java index 397c02c..83bb471 100644 --- a/lib/src/main/java/com/parkertenbroeck/generators/loadtime/StateMachineBuilder.java +++ b/lib/src/main/java/com/parkertenbroeck/bcms/loadtime/StateMachineBuilder.java @@ -1,4 +1,4 @@ -package com.parkertenbroeck.generators.loadtime; +package com.parkertenbroeck.bcms.loadtime; import java.lang.classfile.*; import java.lang.classfile.attribute.InnerClassInfo; @@ -65,8 +65,8 @@ public abstract class StateMachineBuilder> { .replace("[", "_____") ) .collect(Collectors.joining("$")); - innerClassName = method_name; - var name = cdn + "$" +innerClassName; + innerClassName = method_name + "______" + param_cnd; + var name = cdn + "$" + innerClassName; this.CD_this = ClassDesc.of(src_clm.thisClass().asSymbol().packageName(), name); this.params = mts.parameterArray(); @@ -116,7 +116,7 @@ public abstract class StateMachineBuilder> { if(shouldBeInnerClass()){ src_clm.findAttributes(Attributes.sourceFile()).forEach(clb::with); - clb.with(InnerClassesAttribute.of(InnerClassInfo.of(CD_this, Optional.of(src_clm.thisClass().asSymbol()), Optional.of(innerClassName), AccessFlag.PUBLIC))); + clb.with(InnerClassesAttribute.of(InnerClassInfo.of(CD_this, Optional.empty(), Optional.empty(), AccessFlag.PUBLIC))); clb.with(NestHostAttribute.of(src_clm.thisClass())); } @@ -128,7 +128,7 @@ public abstract class StateMachineBuilder> { clb.withField(STATE_NAME, ConstantDescs.CD_int, ClassFile.ACC_PRIVATE); // constructor - clb.withMethod(ConstantDescs.INIT_NAME, MTD_init, ClassFile.ACC_PUBLIC, mb -> mb.withCode(cob -> { + clb.withMethod(ConstantDescs.INIT_NAME, MTD_init, ClassFile.ACC_PRIVATE, mb -> mb.withCode(cob -> { cob.aload(0).invokespecial(ConstantDescs.CD_Object, ConstantDescs.INIT_NAME, ConstantDescs.MTD_void); params(1, (param, slot, type) -> { cob.aload(0).loadLocal(TypeKind.from(type), slot).putfield(CD_this, param, type); diff --git a/lib/src/main/java/com/parkertenbroeck/generators/loadtime/GeneratorClassLoader.java b/lib/src/main/java/com/parkertenbroeck/bcms/loadtime/StateMachineClassLoader.java similarity index 55% rename from lib/src/main/java/com/parkertenbroeck/generators/loadtime/GeneratorClassLoader.java rename to lib/src/main/java/com/parkertenbroeck/bcms/loadtime/StateMachineClassLoader.java index 04a63e1..c431a4f 100644 --- a/lib/src/main/java/com/parkertenbroeck/generators/loadtime/GeneratorClassLoader.java +++ b/lib/src/main/java/com/parkertenbroeck/bcms/loadtime/StateMachineClassLoader.java @@ -1,25 +1,65 @@ -package com.parkertenbroeck.generators.loadtime; +package com.parkertenbroeck.bcms.loadtime; import com.parkertenbroeck.future.Future; -import com.parkertenbroeck.gen.Gen; -import com.parkertenbroeck.generators.loadtime.future.FutureSMBuilder; -import com.parkertenbroeck.generators.loadtime.gen.GenSMBuilder; +import com.parkertenbroeck.generator.Gen; +import com.parkertenbroeck.bcms.loadtime.future.FutureSMBuilder; +import com.parkertenbroeck.bcms.loadtime.gen.GenSMBuilder; import java.io.IOException; import java.lang.classfile.*; import java.lang.classfile.attribute.*; import java.lang.classfile.constantpool.ClassEntry; import java.lang.constant.ClassDesc; -import java.lang.reflect.AccessFlag; import java.nio.file.Files; import java.nio.file.Path; import java.util.*; -public class GeneratorClassLoader extends ClassLoader { +public class StateMachineClassLoader extends ClassLoader { private final HashMap> customClazzMap = new HashMap<>(); + private final List skip; + private final HashMap builders; - public GeneratorClassLoader(ClassLoader parent) { + public interface SMBB{ + StateMachineBuilder build(ClassModel src_clm, MethodModel src_mem, CodeModel src_com); + } + public static class Config{ + HashSet skip = new HashSet<>(); + HashMap builders = new HashMap<>(); + + public static Config empty(){ + return new Config(); + } + public static Config builtin(){ + return empty() + .skip("java", "jdk", "jre", "com.parkertenbroeck.generators.loadtime") + .with(Future.class, FutureSMBuilder::new) + .with(Gen.class, GenSMBuilder::new); + } + + public Config skip(String... paths){ + skip.addAll(List.of(paths)); + return this; + } + + public Config with(Class ret, SMBB builder){ + builders.put(ClassDesc.ofDescriptor(ret.descriptorString()), builder); + return this; + } + + public Config with(ClassDesc ret, SMBB builder){ + builders.put(ret, builder); + return this; + } + } + + public StateMachineClassLoader(ClassLoader parent) { + this(parent, Config.builtin()); + } + + public StateMachineClassLoader(ClassLoader parent, Config config) { super(parent); + skip = config.skip.stream().toList(); + builders = new HashMap<>(config.builders); } void add(String name, byte[] def){ @@ -36,23 +76,23 @@ public class GeneratorClassLoader extends ClassLoader { public Class loadClass(String name) throws ClassNotFoundException { if (customClazzMap.get(name) instanceof Class clazz) return clazz; - if (name.startsWith("java")) - return super.loadClass(name); + for(var item : skip) + if(name.startsWith(item)) + return super.loadClass(name); + var p = "/" + name.replace('.', '/') + ".class"; - try (var stream = GeneratorClassLoader.class.getResourceAsStream(p)) { + try (var stream = StateMachineClassLoader.class.getResourceAsStream(p)) { var bytes = Objects.requireNonNull(stream).readAllBytes(); - add(name, searchReplaceMethods(bytes)); + add(name, searchReplaceableMethods(bytes)); return customClazzMap.get(name); } catch (IOException e) { throw new ClassNotFoundException(name, e); } } - public byte[] searchReplaceMethods(byte[] in) { + public byte[] searchReplaceableMethods(byte[] in) { var clm = ClassFile.of(ClassFile.AttributesProcessingOption.PASS_ALL_ATTRIBUTES).parse(in); - var isGen = clm.thisClass().asSymbol().descriptorString().equals(Gen.class.descriptorString()); - var isFuture = clm.thisClass().asSymbol().descriptorString().equals(Future.class.descriptorString()); var nestMem = new ArrayList(); @@ -62,23 +102,21 @@ public class GeneratorClassLoader extends ClassLoader { return ClassFile.of(ClassFile.AttributesProcessingOption.PASS_ALL_ATTRIBUTES, ClassFile.StackMapsOption.STACK_MAPS_WHEN_REQUIRED).build(clm.thisClass().asSymbol(), cb -> { for (var ce : clm) { - if (ce instanceof MethodModel mem && !isGen && !isFuture && mem.code().isPresent()) { - StateMachineBuilder builder; - if(mem.methodTypeSymbol().returnType().descriptorString().equals(Gen.class.descriptorString())){ - builder = new GenSMBuilder(clm, mem, mem.code().get()); - }else if(mem.methodTypeSymbol().returnType().descriptorString().equals(Future.class.descriptorString())){ - builder = new FutureSMBuilder(clm, mem, mem.code().get()); - }else{ - builder= null; - } + if (ce instanceof MethodModel mem && mem.code().isPresent()) { + StateMachineBuilder builder = builders + .getOrDefault( + mem.methodTypeSymbol().returnType(), + (_, _, _) -> null + ).build(clm, mem, mem.code().get()); + if(builder!=null&&builder.hasAnyHandlers()){ add(builder.CD_this.packageName() + "." + builder.CD_this.displayName(), builder.buildStateMachine()); cb.withMethod(mem.methodName(), mem.methodType(), mem.flags().flagsMask()&~ClassFile.ACC_SYNCHRONIZED, mb -> { mb.withCode(builder::buildSourceMethodShim); }); if(builder.shouldBeInnerClass()){ - innerCl.add(InnerClassInfo.of(builder.CD_this, Optional.of(clm.thisClass().asSymbol()), Optional.of(builder.innerClassName))); - nestMem.add(ClassDesc.of(builder.CD_this.displayName())); + innerCl.add(InnerClassInfo.of(builder.CD_this, Optional.empty(), Optional.empty())); + nestMem.add(builder.CD_this); } }else{ cb.with(mem); diff --git a/lib/src/main/java/com/parkertenbroeck/generators/loadtime/future/Cancellation.java b/lib/src/main/java/com/parkertenbroeck/bcms/loadtime/future/Cancellation.java similarity index 78% rename from lib/src/main/java/com/parkertenbroeck/generators/loadtime/future/Cancellation.java rename to lib/src/main/java/com/parkertenbroeck/bcms/loadtime/future/Cancellation.java index febddcf..df88e89 100644 --- a/lib/src/main/java/com/parkertenbroeck/generators/loadtime/future/Cancellation.java +++ b/lib/src/main/java/com/parkertenbroeck/bcms/loadtime/future/Cancellation.java @@ -1,4 +1,4 @@ -package com.parkertenbroeck.generators.loadtime.future; +package com.parkertenbroeck.bcms.loadtime.future; import java.lang.annotation.*; diff --git a/lib/src/main/java/com/parkertenbroeck/generators/loadtime/future/FutureSMBuilder.java b/lib/src/main/java/com/parkertenbroeck/bcms/loadtime/future/FutureSMBuilder.java similarity index 99% rename from lib/src/main/java/com/parkertenbroeck/generators/loadtime/future/FutureSMBuilder.java rename to lib/src/main/java/com/parkertenbroeck/bcms/loadtime/future/FutureSMBuilder.java index ca7725f..d4ea2c5 100644 --- a/lib/src/main/java/com/parkertenbroeck/generators/loadtime/future/FutureSMBuilder.java +++ b/lib/src/main/java/com/parkertenbroeck/bcms/loadtime/future/FutureSMBuilder.java @@ -1,8 +1,8 @@ -package com.parkertenbroeck.generators.loadtime.future; +package com.parkertenbroeck.bcms.loadtime.future; import com.parkertenbroeck.future.Future; import com.parkertenbroeck.future.Waker; -import com.parkertenbroeck.generators.loadtime.*; +import com.parkertenbroeck.bcms.loadtime.*; import java.lang.classfile.*; import java.lang.classfile.instruction.SwitchCase; diff --git a/lib/src/main/java/com/parkertenbroeck/generators/loadtime/gen/GenSMBuilder.java b/lib/src/main/java/com/parkertenbroeck/bcms/loadtime/gen/GenSMBuilder.java similarity index 97% rename from lib/src/main/java/com/parkertenbroeck/generators/loadtime/gen/GenSMBuilder.java rename to lib/src/main/java/com/parkertenbroeck/bcms/loadtime/gen/GenSMBuilder.java index a14a39c..384b5cc 100644 --- a/lib/src/main/java/com/parkertenbroeck/generators/loadtime/gen/GenSMBuilder.java +++ b/lib/src/main/java/com/parkertenbroeck/bcms/loadtime/gen/GenSMBuilder.java @@ -1,7 +1,7 @@ -package com.parkertenbroeck.generators.loadtime.gen; +package com.parkertenbroeck.bcms.loadtime.gen; -import com.parkertenbroeck.gen.Gen; -import com.parkertenbroeck.generators.loadtime.*; +import com.parkertenbroeck.generator.Gen; +import com.parkertenbroeck.bcms.loadtime.*; import java.lang.classfile.*; import java.lang.constant.ClassDesc; diff --git a/lib/src/main/java/com/parkertenbroeck/gen/Gen.java b/lib/src/main/java/com/parkertenbroeck/generator/Gen.java similarity index 94% rename from lib/src/main/java/com/parkertenbroeck/gen/Gen.java rename to lib/src/main/java/com/parkertenbroeck/generator/Gen.java index e9307d8..5bcaaa5 100644 --- a/lib/src/main/java/com/parkertenbroeck/gen/Gen.java +++ b/lib/src/main/java/com/parkertenbroeck/generator/Gen.java @@ -1,4 +1,4 @@ -package com.parkertenbroeck.gen; +package com.parkertenbroeck.generator; public interface Gen { Res next(); diff --git a/lib/src/main/java/com/parkertenbroeck/generators/RT.java b/lib/src/main/java/com/parkertenbroeck/generators/RT.java deleted file mode 100644 index 8477ba3..0000000 --- a/lib/src/main/java/com/parkertenbroeck/generators/RT.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.parkertenbroeck.generators; - - -import com.parkertenbroeck.generators.loadtime.GeneratorClassLoader; - -public class RT { - public static void runWithGeneratorSupport(Class clazz){ - var loader = new GeneratorClassLoader(RT.class.getClassLoader()); - try{ - ((Runnable)loader.loadClass(clazz.getName()).getConstructor().newInstance()).run(); - }catch (Exception e){ - throw new RuntimeException(e); - } - } -}