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  }