github.com/lmorg/murex@v0.0.0-20240217211045-e081c89cd4ef/lang/interpreter_pc.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 exitNum = (*procs)[i].ExitNum 71 72 if tryErr { 73 checkTryErr(&(*procs)[i], &exitNum) 74 } 75 76 if next < len(*procs) { 77 if exitNum < 1 && (*procs)[next].OperatorLogicOr { 78 i++ 79 (*procs)[i].hasTerminatedM.Lock() 80 (*procs)[i].hasTerminatedV = true 81 (*procs)[i].hasTerminatedM.Unlock() 82 (*procs)[i].Stdout.Close() 83 (*procs)[i].Stderr.Close() 84 GlobalFIDs.Deregister((*procs)[i].Id) 85 (*procs)[i].State.Set(state.AwaitingGC) 86 continue 87 } 88 89 if exitNum > 0 && !(*procs)[next].OperatorLogicOr { 90 for i++; i < len(*procs); i++ { 91 (*procs)[i].Stdout.Close() 92 (*procs)[i].Stderr.Close() 93 GlobalFIDs.Deregister((*procs)[i].Id) 94 (*procs)[i].State.Set(state.AwaitingGC) 95 } 96 return 97 } 98 } 99 100 } else { 101 go waitProcess(&(*procs)[i]) 102 } 103 } 104 105 return 106 } 107 108 // `trypipe` - Each process in the pipeline is tried sequentially. Breaks parallelization. 109 func runModeTryPipe(procs *[]Process, tryPipeErr bool) (exitNum int) { 110 if len(*procs) == 0 { 111 return 1 112 } 113 114 for i := 0; i < len(*procs); i++ { 115 go executeProcess(&(*procs)[i]) 116 waitProcess(&(*procs)[i]) 117 118 exitNum = (*procs)[i].ExitNum 119 120 if tryPipeErr { 121 checkTryErr(&(*procs)[i], &exitNum) 122 } 123 124 next := i + 1 125 if next < len(*procs) { 126 if exitNum < 1 && (*procs)[next].OperatorLogicOr { 127 i++ 128 (*procs)[i].hasTerminatedM.Lock() 129 (*procs)[i].hasTerminatedV = true 130 (*procs)[i].hasTerminatedM.Unlock() 131 (*procs)[i].Stdout.Close() 132 (*procs)[i].Stderr.Close() 133 GlobalFIDs.Deregister((*procs)[i].Id) 134 (*procs)[i].State.Set(state.AwaitingGC) 135 continue 136 } 137 138 if exitNum > 0 && !(*procs)[next].OperatorLogicOr { 139 for i++; i < len(*procs); i++ { 140 (*procs)[i].Stdout.Close() 141 (*procs)[i].Stderr.Close() 142 GlobalFIDs.Deregister((*procs)[i].Id) 143 (*procs)[i].State.Set(state.AwaitingGC) 144 } 145 return 146 } 147 } 148 } 149 150 return 151 }