github.com/lmorg/murex@v0.0.0-20240217211045-e081c89cd4ef/lang/interpreter_js.go (about) 1 //go:build js 2 // +build js 3 4 package lang 5 6 import ( 7 "github.com/lmorg/murex/lang/state" 8 ) 9 10 ////////////////// 11 // Schedulers // 12 ////////////////// 13 14 func runModeNormal(procs *[]Process) (exitNum int) { 15 var ( 16 prev int 17 skipPipeline bool 18 ) 19 20 if len(*procs) == 0 { 21 return 1 22 } 23 24 for i := range *procs { 25 if i > 0 { 26 27 prev = i - 1 28 29 if (*procs)[i].IsMethod { 30 go waitProcess(&(*procs)[prev]) 31 } else { 32 waitProcess(&(*procs)[prev]) 33 } 34 35 if ((*procs)[i].OperatorLogicAnd && (*procs)[prev].ExitNum != 0) || 36 ((*procs)[i].OperatorLogicOr && (*procs)[prev].ExitNum == 0) || 37 (skipPipeline && ((*procs)[i].OperatorLogicAnd || (*procs)[i].OperatorLogicOr)) { 38 39 (*procs)[i].hasTerminatedM.Lock() 40 (*procs)[i].hasTerminatedV = true 41 (*procs)[i].hasTerminatedM.Unlock() 42 (*procs)[i].ExitNum = (*procs)[prev].ExitNum 43 skipPipeline = true 44 } else { 45 skipPipeline = false 46 } 47 } 48 49 go executeProcess(&(*procs)[i]) 50 } 51 52 waitProcess(&(*procs)[len(*procs)-1]) 53 exitNum = (*procs)[len(*procs)-1].ExitNum 54 55 return 56 } 57 58 // `try` - Last process in each pipe is checked. 59 func runModeTry(procs *[]Process, tryErr bool) (exitNum int) { 60 if len((*procs)) == 0 { 61 return 1 62 } 63 64 for i := 0; i < len(*procs); i++ { 65 go executeProcess(&(*procs)[i]) 66 next := i + 1 67 68 if next == len((*procs)) || !(*procs)[next].IsMethod { 69 waitProcess(&(*procs)[i]) 70 71 exitNum = (*procs)[i].ExitNum 72 73 if tryErr { 74 checkTryErr(&(*procs)[i], &exitNum) 75 } 76 77 if next < len(*procs) { 78 if exitNum < 1 && (*procs)[next].OperatorLogicOr { 79 i++ 80 (*procs)[i].hasTerminatedM.Lock() 81 (*procs)[i].hasTerminatedV = true 82 (*procs)[i].hasTerminatedM.Unlock() 83 (*procs)[i].Stdout.Close() 84 (*procs)[i].Stderr.Close() 85 GlobalFIDs.Deregister((*procs)[i].Id) 86 (*procs)[i].State.Set(state.AwaitingGC) 87 continue 88 } 89 90 if exitNum > 0 && !(*procs)[next].OperatorLogicOr { 91 for i++; i < len(*procs); i++ { 92 (*procs)[i].Stdout.Close() 93 (*procs)[i].Stderr.Close() 94 GlobalFIDs.Deregister((*procs)[i].Id) 95 (*procs)[i].State.Set(state.AwaitingGC) 96 } 97 return 98 } 99 } 100 101 } else { 102 go waitProcess(&(*procs)[i]) 103 } 104 } 105 106 return 107 } 108 109 // `trypipe` - Each process in the pipeline is tried sequentially. Breaks parallelization. 110 func runModeTryPipe(procs *[]Process, tryPipeErr bool) (exitNum int) { 111 if len(*procs) == 0 { 112 return 1 113 } 114 115 for i := 0; i < len(*procs); i++ { 116 go executeProcess(&(*procs)[i]) 117 waitProcess(&(*procs)[i]) 118 119 exitNum = (*procs)[i].ExitNum 120 121 if tryPipeErr { 122 checkTryErr(&(*procs)[i], &exitNum) 123 } 124 125 next := i + 1 126 if next < len(*procs) { 127 if exitNum < 1 && (*procs)[next].OperatorLogicOr { 128 i++ 129 (*procs)[i].hasTerminatedM.Lock() 130 (*procs)[i].hasTerminatedV = true 131 (*procs)[i].hasTerminatedM.Unlock() 132 (*procs)[i].Stdout.Close() 133 (*procs)[i].Stderr.Close() 134 GlobalFIDs.Deregister((*procs)[i].Id) 135 (*procs)[i].State.Set(state.AwaitingGC) 136 continue 137 } 138 139 if exitNum > 0 && !(*procs)[next].OperatorLogicOr { 140 for i++; i < len(*procs); i++ { 141 (*procs)[i].Stdout.Close() 142 (*procs)[i].Stderr.Close() 143 GlobalFIDs.Deregister((*procs)[i].Id) 144 (*procs)[i].State.Set(state.AwaitingGC) 145 } 146 return 147 } 148 } 149 } 150 151 return 152 }