1212import mx .kenzie .foundation .WriteInstruction ;
1313import org .byteskript .skript .api .HandlerType ;
1414import org .byteskript .skript .api .note .Documentation ;
15- import org .byteskript .skript .api .note .ForceExtract ;
1615import org .byteskript .skript .api .syntax .ControlEffect ;
1716import org .byteskript .skript .compiler .*;
1817import org .byteskript .skript .compiler .structure .PreVariable ;
19- import org .byteskript .skript .error .ScriptRuntimeError ;
2018import org .byteskript .skript .lang .element .StandardElements ;
2119import org .byteskript .skript .lang .handler .StandardHandlers ;
2220import org .byteskript .skript .lang .syntax .flow .lambda .SupplierSection ;
2321import org .byteskript .skript .runtime .internal .ExtractedSyntaxCalls ;
2422import org .byteskript .skript .runtime .threading .ScriptThread ;
2523import org .objectweb .asm .Handle ;
24+ import org .objectweb .asm .Label ;
2625import org .objectweb .asm .Opcodes ;
2726
2827import java .lang .invoke .LambdaMetafactory ;
3635 name = "Wait For" ,
3736 description = """
3837 Runs the given executable in the background.
39- Background processes ignore waits from the current process.
38+ The current process will wait for completion or a `wake` call.
39+ After a wake call both processes will run in parallel.
4040 """ ,
4141 examples = {
4242 """
43- run {function} in the background
44- run {runnable} in the background
45- """
43+ wait for {function}
44+ wait for {runnable}
45+ """
4646 }
4747)
4848public class WaitForEffect extends ControlEffect {
@@ -51,21 +51,6 @@ public WaitForEffect() {
5151 super (SkriptLangSpec .LIBRARY , StandardElements .EFFECT , "wait for %Executable%" );
5252 }
5353
54- @ ForceExtract
55- public static Object getLock () {
56- if (!(Thread .currentThread () instanceof ScriptThread thread ))
57- throw new ScriptRuntimeError ("Unable to put non-script thread to sleep." );
58- return thread .lock ;
59- }
60-
61- @ ForceExtract
62- public static void unlock () {
63- final ScriptThread thread = ((ScriptThread ) Thread .currentThread ());
64- synchronized (thread .lock ) {
65- thread .lock .notify ();
66- }
67- }
68-
6954 @ Override
7055 public Pattern .Match match (String thing , Context context ) {
7156 if (!thing .startsWith ("wait for " )) return null ;
@@ -100,18 +85,40 @@ public void preCompile(Context context, Pattern.Match match) throws Throwable {
10085 .setReturnType (new Type (void .class ));
10186 SupplierSection .extractVariables (context , method , child );
10287 context .setMethod (child );
88+ final Label start = new Label (), end = new Label (), after = new Label ();
89+ tree .metadata .put ("end" , end );
90+ tree .metadata .put ("after" , after );
91+ child .writeCode ((writer , visitor ) -> {
92+ visitor .visitTryCatchBlock (start , end , after , null );
93+ visitor .visitLabel (start );
94+ });
10395 }
10496
10597 @ Override
10698 public void compile (Context context , Pattern .Match match ) throws Throwable {
10799 final ElementTree tree = context .getCompileCurrent ();
108100 final int variable = (int ) tree .metadata .get ("variable" );
109101 final String location = new Type (ScriptThread .class ).internalName ();
102+ final Label end = ((Label ) tree .metadata .get ("end" ));
103+ final Label after = ((Label ) tree .metadata .get ("after" ));
104+ final Label jump = new Label (), rethrow = new Label ();
105+ final PreVariable store = new PreVariable ("error" );
106+ context .forceUnspecVariable (store );
107+ final int error = context .slotOf (store );
110108 final MethodBuilder method ;
111109 {
112110 final MethodBuilder child = context .getMethod ();
113111 this .writeCall (child , RunEffect .class .getMethod ("run" , Object .class ), context );
114112 child .writeCode ((writer , visitor ) -> {
113+ visitor .visitJumpInsn (167 , jump );
114+ visitor .visitLabel (after );
115+ visitor .visitFrame (Opcodes .F_SAME1 , 0 , null , 1 , new Object []{"java/lang/Throwable" });
116+ visitor .visitVarInsn (58 , error );
117+ visitor .visitJumpInsn (167 , rethrow );
118+ visitor .visitLabel (end );
119+ });
120+ child .writeCode ((writer , visitor ) -> {
121+ visitor .visitLabel (jump );
115122 visitor .visitVarInsn (Opcodes .ALOAD , variable );
116123 visitor .visitTypeInsn (192 , location );
117124 visitor .visitFieldInsn (180 , location , "lock" , "Ljava/lang/Object;" );
@@ -120,8 +127,13 @@ public void compile(Context context, Pattern.Match match) throws Throwable {
120127 visitor .visitInsn (Opcodes .MONITORENTER );
121128 visitor .visitMethodInsn (182 , "java/lang/Object" , "notify" , "()V" , false );
122129 visitor .visitInsn (Opcodes .MONITOREXIT );
130+ visitor .visitInsn (Opcodes .RETURN );
131+ visitor .visitLabel (rethrow );
132+ visitor .visitVarInsn (25 , error );
133+ visitor .visitInsn (Opcodes .ATHROW );
134+ visitor .visitInsn (Opcodes .RETURN );
135+
123136 });
124- this .writeCall (child , WaitForEffect .class .getMethod ("unlock" ), context );
125137 child .writeCode (WriteInstruction .returnEmpty ());
126138 final String internal = context .getType ().internalName ();
127139 method = context .getTriggerMethod ();
0 commit comments