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  }