diff --git a/src/Examples.java b/src/Examples.java index 71e79d9..92735a4 100644 --- a/src/Examples.java +++ b/src/Examples.java @@ -1,3 +1,4 @@ +import generator.future.Future; import generator.gen.Gen; public class Examples { @@ -65,25 +66,22 @@ public class Examples { // return Gen.ret(); // } - public static Gen awaitTest2(int number){ - for(int i = 0; i < number; i ++)Gen.yield(); - return Gen.ret(number+""); - } +// public static Future awaitTest2(int number){ +// for(int i = 0; i < number; i ++)Future.yield(); +// return Future.ret(number+""); +// } - public static class Meow implements AutoCloseable{ - { - System.out.println("Opened"); - } - @Override - public void close() { - System.out.println("Closed"); - } - } - - public static Gen awaitTest(int number){ - try(var m = new Meow()){ - return Gen.ret(awaitTest2(number).await()); - } + public static Future awaitTest(int number){ + int i = 0; +// Future.yield(); +// i = 1; +// Future.yield(); +// i += i*12; +// Future.yield(); +// return Future.ret(awaitTest2(number).await()); + for(; i < number; i++) + Future.yield(); + return Future.ret("meow"+i); } // public static Gen test(double[] nyas){ diff --git a/src/Main.java b/src/Main.java index 292420a..5f3bf7a 100644 --- a/src/Main.java +++ b/src/Main.java @@ -1,4 +1,5 @@ import generator.RT; +import generator.future.Future; import generator.gen.Gen; import java.util.function.Supplier; @@ -10,47 +11,45 @@ public class Main implements Runnable { @Override public void run() { -// await(); - lexer(); + await(); +// lexer(); // lambda(); } - void lambda(){ - var gen = ((Supplier>)() -> { - Gen.yield(12); - return Gen.ret("hello"); - }).get(); - - while(true) { - var next = gen.next(); - if(next instanceof Gen.Yield(var e)) System.out.println(e); - else if(next instanceof Gen.Ret(var ret)){ - System.out.println(ret); - break; - } - } - } +// void lambda(){ +// var gen = ((Supplier>)() -> { +// Gen.yield(12); +// return Gen.ret("hello"); +// }).get(); +// +// while(true) { +// var next = gen.next(); +// if(next instanceof Gen.Yield(var e)) System.out.println(e); +// else if(next instanceof Gen.Ret(var ret)){ +// System.out.println(ret); +// break; +// } +// } +// } void await(){ var gen = Examples.awaitTest(10); while(true) { - var next = gen.next(); - if(next instanceof Gen.Yield(var e)) System.out.println(e); - else if(next instanceof Gen.Ret(var ret)){ - System.out.println(ret); + var next = (Object)gen.poll(() -> {}); + if(!(next instanceof Future.Pending)){ + System.out.println(next); break; } - } - - Runnable meow = () -> {}; - } - - - 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)"); -// var gen = Examples.test(new double[]{1,2,3,4}); - while(gen.next() instanceof Gen.Yield(var tok)) { - System.out.println(tok); + System.out.println("Pending"); } } + + +// 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)"); +//// var gen = Examples.test(new double[]{1,2,3,4}); +// while(gen.next() instanceof Gen.Yield(var tok)) { +// System.out.println(tok); +// } +// } } \ No newline at end of file diff --git a/src/generator/future/Future.java b/src/generator/future/Future.java index b8293be..121bd0d 100644 --- a/src/generator/future/Future.java +++ b/src/generator/future/Future.java @@ -4,19 +4,23 @@ public interface Future { @SuppressWarnings("unchecked") default R poll(Waker waker){ - return (R) Pending.INSTANCE; + return (R)Pending.INSTANCE; } default R await(){ - throw new RuntimeException(); + throw new RuntimeException("NO!"); } static Future ret(R r){ - throw new RuntimeException(); + throw new RuntimeException("NO!"); + } + + static void yield() { + throw new RuntimeException("NO!"); } final class Pending{ - private static final Pending INSTANCE = new Pending(); + public static final Pending INSTANCE = new Pending(); private Pending(){} } } diff --git a/src/generator/runtime/GeneratorClassLoader.java b/src/generator/runtime/GeneratorClassLoader.java index 4ec63af..f360a04 100644 --- a/src/generator/runtime/GeneratorClassLoader.java +++ b/src/generator/runtime/GeneratorClassLoader.java @@ -1,6 +1,8 @@ package generator.runtime; +import generator.future.Future; import generator.gen.Gen; +import generator.runtime.future.FutureSMBuilder; import generator.runtime.gen.GenSMBuilder; import java.io.IOException; @@ -8,6 +10,7 @@ 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.*; @@ -39,16 +42,17 @@ public class GeneratorClassLoader extends ClassLoader { var p = "/" + name.replace('.', '/') + ".class"; try (var stream = GeneratorClassLoader.class.getResourceAsStream(p)) { var bytes = Objects.requireNonNull(stream).readAllBytes(); - add(name, searchForGenerators(bytes)); + add(name, searchReplaceMethods(bytes)); return customClazzMap.get(name); } catch (IOException e) { throw new ClassNotFoundException(name, e); } } - public byte[] searchForGenerators(byte[] in) { + public byte[] searchReplaceMethods(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(); @@ -58,14 +62,18 @@ public class GeneratorClassLoader extends ClassLoader { return ClassFile.of(ClassFile.AttributesProcessingOption.PASS_ALL_ATTRIBUTES).build(clm.thisClass().asSymbol(), cb -> { for (var ce : clm) { - if (ce instanceof MethodModel mem && !isGen) { - var methodRetGen = mem.methodTypeSymbol().returnType().descriptorString().equals(Gen.class.descriptorString()); - if (!methodRetGen) { + if (ce instanceof MethodModel mem && !isGen && !isFuture) { + StateMachineBuilder builder = null; + if(mem.methodTypeSymbol().returnType().descriptorString().equals(Gen.class.descriptorString())){ + builder = generatorMethod(cb, mem, clm); + }else if(mem.methodTypeSymbol().returnType().descriptorString().equals(Future.class.descriptorString())){ + builder = futureMethod(cb, mem, clm); + }else{ cb.with(mem); - } else{ - var gcd = generatorMethod(cb, mem, clm); -// innerCl.add(InnerClassInfo.of(gcd, Optional.of(clm.thisClass().asSymbol()), Optional.of(gcd.displayName()), AccessFlag.PUBLIC, AccessFlag.FINAL, AccessFlag.STATIC)); -// nestMem.add(ClassDesc.of(gcd.displayName())); + } + if(builder != null && builder.shouldBeInnerClass()){ + innerCl.add(InnerClassInfo.of(builder.CD_this, Optional.of(clm.thisClass().asSymbol()), Optional.of(builder.CD_this.displayName()), AccessFlag.PUBLIC, AccessFlag.FINAL, AccessFlag.STATIC)); + nestMem.add(ClassDesc.of(builder.CD_this.displayName())); } } else if (ce instanceof Attribute e){ @@ -81,13 +89,23 @@ public class GeneratorClassLoader extends ClassLoader { }); } - private ClassDesc generatorMethod(ClassBuilder cb, MethodModel src_mem, ClassModel src_clm) { + private StateMachineBuilder generatorMethod(ClassBuilder cb, MethodModel src_mem, ClassModel src_clm) { var com = src_mem.code().get(); - var gb = new GenSMBuilder(src_clm, src_mem, com); - add(gb.CD_this.displayName(), gb.buildStateMachine()); + var smb = new GenSMBuilder(src_clm, src_mem, com); + add(smb.CD_this.displayName(), smb.buildStateMachine()); cb.withMethod(src_mem.methodName(), src_mem.methodType(), src_mem.flags().flagsMask(), mb -> { - mb.withCode(gb::buildSourceMethodShim); + mb.withCode(smb::buildSourceMethodShim); }); - return gb.CD_this; + return smb; + } + + private StateMachineBuilder futureMethod(ClassBuilder cb, MethodModel src_mem, ClassModel src_clm) { + var com = src_mem.code().get(); + var smb = new FutureSMBuilder(src_clm, src_mem, com); + add(smb.CD_this.displayName(), smb.buildStateMachine()); + cb.withMethod(src_mem.methodName(), src_mem.methodType(), src_mem.flags().flagsMask(), mb -> { + mb.withCode(smb::buildSourceMethodShim); + }); + return smb; } } diff --git a/src/generator/runtime/LocalTracker.java b/src/generator/runtime/LocalTracker.java index c68ed7e..bb3a397 100644 --- a/src/generator/runtime/LocalTracker.java +++ b/src/generator/runtime/LocalTracker.java @@ -60,8 +60,8 @@ public class LocalTracker { name = StateMachineBuilder.LOCAL_PREFIX + localStore.size(); localStore.add(new LocalStore(name, desc)); } - saved.add(new Saved(slot, name, desc)); - cob.aload(0).loadLocal(tk, slot).putfield(cd, name, desc); + saved.add(new Saved(slot+1, name, desc)); + cob.aload(0).loadLocal(tk, slot+1).putfield(cd, name, desc); }); run.run(); @@ -98,7 +98,7 @@ public class LocalTracker { public void currentLocals(LocalConsumer consumer) { var slot = 0; - if (currentFrame != null) + if (currentFrame != null && false) for (var kind : currentFrame.locals()) { switch (kind) { case StackMapFrameInfo.ObjectVerificationTypeInfo o -> { @@ -129,10 +129,10 @@ public class LocalTracker { case StackMapFrameInfo.UninitializedVerificationTypeInfo _ -> throw new IllegalStateException(); } } - for (var entry : localVarTypes.entrySet()) { - if (entry.getKey() < slot) continue; - ClassDesc cd = entry.getValue().upperBound(); - consumer.consume(entry.getKey(), TypeKind.from(cd), cd); - } +// for (var entry : localVarTypes.entrySet()) { +// if (entry.getKey() < slot) continue; +// ClassDesc cd = entry.getValue().upperBound(); +// consumer.consume(entry.getKey(), TypeKind.from(cd), cd); +// } } } diff --git a/src/generator/runtime/StateMachineBuilder.java b/src/generator/runtime/StateMachineBuilder.java index 35fc336..7ccf4b9 100644 --- a/src/generator/runtime/StateMachineBuilder.java +++ b/src/generator/runtime/StateMachineBuilder.java @@ -36,7 +36,7 @@ public abstract class StateMachineBuilder { private final ArrayList stateSwitchCases = new ArrayList<>(); - protected final String uniqueName(){ + protected String uniqueName(){ return sequence+++""; } @@ -116,9 +116,9 @@ public abstract class StateMachineBuilder { protected abstract void buildStateMachineMethod(ClassBuilder clb); - public void buildStateMachineMethodCode(ClassBuilder clb, CodeBuilder cob){ + public void buildStateMachineMethodCode(ClassBuilder clb, CodeBuilder cob, int loc_param_off){ cob.trying( - tcob -> buildStateMachineCode(clb, tcob), + tcob -> buildStateMachineCode(clb, tcob, loc_param_off), // catch anything set our state to -1 and throw the exception ctb -> ctb.catchingAll( blc -> @@ -132,7 +132,7 @@ public abstract class StateMachineBuilder { ).aconst_null().areturn(); } - public void buildStateMachineCode(ClassBuilder clb, CodeBuilder cob) { + public void buildStateMachineCode(ClassBuilder clb, CodeBuilder cob, int loc_param_off) { boolean ignore_next_pop = false; var invalidState = cob.newLabel(); @@ -187,25 +187,27 @@ public abstract class StateMachineBuilder { continue; } } + if(coe instanceof LocalVariable lv) System.out.println(lv); switch (coe) { // locals which were once function parameters can be ignored case LocalVariable lv when lv.slot() < paramSlotOff -> { } case LocalVariable lv -> - cob.localVariable(lv.slot() - paramSlotOff + 1, lv.name(), lv.type(), lv.startScope(), lv.endScope()); + cob.localVariable(lv.slot() - paramSlotOff + loc_param_off, lv.name(), lv.type(), lv.startScope(), lv.endScope()); // increment indexes into the stack case IncrementInstruction ii when ii.slot() < paramSlotOff -> cob.aload(0).dup().getfield(CD_this, PARAM_PREFIX + ii.slot(), ConstantDescs.CD_int) .loadConstant(ii.constant()).iadd() .putfield(CD_this, PARAM_PREFIX + ii.slot(), ConstantDescs.CD_int); - case IncrementInstruction ii -> cob.iinc(ii.slot() - paramSlotOff + 1, ii.constant()); + case IncrementInstruction ii -> cob.iinc(ii.slot() - paramSlotOff + loc_param_off, ii.constant()); // convert local function parameters to class fields and offset regular locals case LoadInstruction li when li.slot() < paramSlotOff -> cob.aload(0).getfield(CD_this, PARAM_PREFIX + li.slot(), lt.paramType(li.slot())); - case LoadInstruction li -> cob.loadLocal(li.typeKind(), li.slot() - paramSlotOff + 1); + case LoadInstruction li -> + cob.loadLocal(li.typeKind(), li.slot() - paramSlotOff + loc_param_off); // convert local function parameters to class fields and offset regular locals case StoreInstruction ls when ls.slot() < paramSlotOff && ls.typeKind().slotSize() == 2 -> @@ -213,8 +215,8 @@ public abstract class StateMachineBuilder { case StoreInstruction ls when ls.slot() < paramSlotOff -> cob.aload(0).swap().putfield(CD_this, PARAM_PREFIX + ls.slot(), lt.paramType(ls.slot())); case StoreInstruction ls -> { - lt.trackLocal(ls.slot() - paramSlotOff + 1, ls.typeKind()); - cob.storeLocal(ls.typeKind(), ls.slot() - paramSlotOff + 1); + lt.trackLocal(ls.slot() - paramSlotOff + loc_param_off, ls.typeKind()); + cob.storeLocal(ls.typeKind(), ls.slot() - paramSlotOff + loc_param_off); } default -> cob.with(coe); diff --git a/src/generator/runtime/future/FutureSMBuilder.java b/src/generator/runtime/future/FutureSMBuilder.java index 52ee690..ff56b93 100644 --- a/src/generator/runtime/future/FutureSMBuilder.java +++ b/src/generator/runtime/future/FutureSMBuilder.java @@ -1,5 +1,7 @@ package generator.runtime.future; +import generator.future.Future; +import generator.future.Waker; import generator.gen.Gen; import generator.runtime.ReplacementKind; import generator.runtime.SpecialMethod; @@ -14,13 +16,12 @@ import java.util.List; public class FutureSMBuilder extends StateMachineBuilder { - public final static ClassDesc CD_Gen = ClassDesc.ofDescriptor(Gen.class.descriptorString()); - public final static ClassDesc CD_Res = ClassDesc.ofDescriptor(Gen.Res.class.descriptorString()); - public final static ClassDesc CD_Yield = ClassDesc.ofDescriptor(Gen.Yield.class.descriptorString()); - public final static ClassDesc CD_Ret = ClassDesc.ofDescriptor(Gen.Ret.class.descriptorString()); - public final static MethodTypeDesc MTD_Res = MethodTypeDesc.of(CD_Res); - public final static MethodTypeDesc MTD_Gen_Obj = MethodTypeDesc.of(CD_Gen, ConstantDescs.CD_Object); - public final static MethodTypeDesc MTD_Gen = MethodTypeDesc.of(CD_Gen); + public final static ClassDesc CD_Future = ClassDesc.ofDescriptor(Future.class.descriptorString()); + public final static ClassDesc CD_Waker = ClassDesc.ofDescriptor(Waker.class.descriptorString()); + public final static ClassDesc CD_Pending = ClassDesc.ofDescriptor(Future.Pending.class.descriptorString()); + + public final static MethodTypeDesc MTD_Future_Obj = MethodTypeDesc.of(CD_Future, ConstantDescs.CD_Object); + public final static MethodTypeDesc MTD_Object_Waker = MethodTypeDesc.of(ConstantDescs.CD_Object, CD_Waker); public final static MethodTypeDesc MTD_Obj = MethodTypeDesc.of(ConstantDescs.CD_Object); static class AwaitHandler implements SpecialMethodHandler{ @@ -38,33 +39,76 @@ public class FutureSMBuilder extends StateMachineBuilder { cob.aload(0).loadConstant(yield_state).putfield(smb.CD_this, STATE_NAME, TypeKind.INT.upperBound()); var start = cob.newBoundLabel(); cob.dup().dup() - .invokeinterface(CD_Gen, "next", MethodTypeDesc.of(CD_Res)).dup() - .instanceOf(CD_Ret); + .aload(1) + .invokeinterface(CD_Future, "poll", MTD_Object_Waker).dup() + .instanceOf(CD_Pending); cob.ifThenElse(bcb -> { - bcb.checkcast(CD_Ret).invokevirtual(CD_Ret, "v", MethodTypeDesc.of(ConstantDescs.CD_Object)).swap().pop(); - }, bcb -> { smb.lt.savingLocals(smb.CD_this, bcb, () -> { - bcb.swap().loadLocal(TypeKind.from(smb.CD_this), 0).swap().putfield(smb.CD_this, "meow", CD_Gen); + bcb.swap().aload(0).swap().putfield(smb.CD_this, "meow", CD_Future); bcb.areturn().labelBinding(yield_label); - bcb.loadLocal(TypeKind.from(smb.CD_this), 0).getfield(smb.CD_this, "meow", CD_Gen); + bcb.aload(0).getfield(smb.CD_this, "meow", CD_Future); }); bcb.goto_(start); + }, bcb -> { + bcb.swap().pop(); }); } } + static class YieldHandler implements SpecialMethodHandler { + final int resume_state; + final Label resume_label; + + public YieldHandler(StateMachineBuilder smb, CodeBuilder cob) { + resume_state = smb.add_state(resume_label = cob.newLabel()); + } + + public ReplacementKind replacementKind(){return ReplacementKind.Immediate;} + + @Override + public void handle(StateMachineBuilder smb, CodeBuilder cob) { + + smb.lt.savingLocals(smb.CD_this, cob, () -> { + cob.aload(0).loadConstant(resume_state).putfield(smb.CD_this, STATE_NAME, TypeKind.INT.upperBound()) + .getstatic(CD_Pending, "INSTANCE", CD_Pending) + .areturn(); + cob.labelBinding(resume_label); + }); + } + } + + static class RetHandler implements SpecialMethodHandler{ + + public RetHandler() {} + + public ReplacementKind replacementKind(){return ReplacementKind.ReplacingNextReturn;} + + @Override + public void handle(StateMachineBuilder smb, CodeBuilder cob) { + cob.aload(0).loadConstant(-1).putfield(smb.CD_this, STATE_NAME, TypeKind.INT.upperBound()).areturn(); + } + } + + @Override + protected String uniqueName() { + return "Fut"+super.uniqueName(); + } + @Override protected void buildStateMachineMethod(ClassBuilder clb){ - clb.withInterfaces(List.of(clb.constantPool().classEntry(CD_Gen))); - clb.withMethod("next", MethodTypeDesc.of(CD_Res), ClassFile.ACC_PUBLIC, mb -> mb.withCode(cob -> { - buildStateMachineMethodCode(clb, cob); + clb.withInterfaces(List.of(clb.constantPool().classEntry(CD_Future))); + clb.withMethod("poll", MTD_Object_Waker, ClassFile.ACC_PUBLIC, mb -> mb.withCode(cob -> { + cob.localVariable(1, "waker", CD_Waker, cob.startLabel(), cob.endLabel()); + buildStateMachineMethodCode(clb, cob, 2); })); - clb.withField("meow", CD_Gen, ClassFile.ACC_PRIVATE); + clb.withField("meow", CD_Future, ClassFile.ACC_PRIVATE); } public FutureSMBuilder(ClassModel src_clm, MethodModel src_mem, CodeModel src_com) { super(src_clm, src_mem, src_com); - smmap.put(new SpecialMethod(CD_Gen, "await", MTD_Obj), AwaitHandler::new); + smmap.put(new SpecialMethod(CD_Future, "await", MTD_Obj), AwaitHandler::new); + smmap.put(new SpecialMethod(CD_Future, "ret", MTD_Future_Obj), (_, _) -> new RetHandler()); + smmap.put(new SpecialMethod(CD_Future, "yield", ConstantDescs.MTD_void), YieldHandler::new); } } diff --git a/src/generator/runtime/gen/GenSMBuilder.java b/src/generator/runtime/gen/GenSMBuilder.java index 9f2cf66..82bf22b 100644 --- a/src/generator/runtime/gen/GenSMBuilder.java +++ b/src/generator/runtime/gen/GenSMBuilder.java @@ -81,11 +81,16 @@ public class GenSMBuilder extends StateMachineBuilder { smmap.put(new SpecialMethod(CD_Gen, "ret", MTD_Gen),(_, _) -> new RetHandler(true)); } + @Override + protected String uniqueName() { + return "Gen"+super.uniqueName(); + } + @Override protected void buildStateMachineMethod(ClassBuilder clb){ clb.withInterfaces(List.of(clb.constantPool().classEntry(CD_Gen))); clb.withMethod("next", MethodTypeDesc.of(CD_Res), ClassFile.ACC_PUBLIC, mb -> mb.withCode(cob -> { - buildStateMachineMethodCode(clb, cob); + buildStateMachineMethodCode(clb, cob, 1); })); } }