github.com/lmorg/murex@v0.0.0-20240217211045-e081c89cd4ef/builtins/core/structs/andor.go (about)

     1  package structs
     2  
     3  import (
     4  	"errors"
     5  
     6  	"github.com/lmorg/murex/lang"
     7  	"github.com/lmorg/murex/lang/types"
     8  )
     9  
    10  func init() {
    11  	lang.DefineFunction("and", cmdAnd, types.Boolean)
    12  	lang.DefineFunction("!and", cmdAnd, types.Boolean)
    13  	lang.DefineFunction("or", cmdOr, types.Boolean)
    14  	lang.DefineFunction("!or", cmdOr, types.Boolean)
    15  }
    16  
    17  const errCancelled = "user has cancelled processing mid-way through the execution of this control flow structure"
    18  
    19  func cmdAnd(p *lang.Process) error { return cmdAndOr(p, true) }
    20  func cmdOr(p *lang.Process) error  { return cmdAndOr(p, false) }
    21  
    22  func cmdAndOr(p *lang.Process, isAnd bool) error {
    23  	p.Stdout.SetDataType(types.Boolean)
    24  
    25  	for i := 0; i < p.Parameters.Len(); i++ {
    26  		if p.HasCancelled() {
    27  			return errors.New(errCancelled)
    28  		}
    29  
    30  		block, err := p.Parameters.Block(i)
    31  		if err != nil {
    32  			return err
    33  		}
    34  
    35  		//stdout := streams.NewStdin()
    36  		//i, err := lang.RunBlockExistingConfigSpace(block, nil, stdout, nil, p)
    37  		fork := p.Fork(lang.F_PARENT_VARTABLE | lang.F_NO_STDIN | lang.F_CREATE_STDOUT | lang.F_NO_STDERR)
    38  		i, err := fork.Execute(block)
    39  		if err != nil {
    40  			return err
    41  		}
    42  
    43  		if p.HasCancelled() {
    44  			return errors.New(errCancelled)
    45  		}
    46  
    47  		b, err := fork.Stdout.ReadAll()
    48  		if err != nil {
    49  			return err
    50  		}
    51  		conditional := types.IsTrue(b, i)
    52  
    53  		if isAnd {
    54  			// --- and ---
    55  			if (!conditional && !p.IsNot) || (conditional && p.IsNot) {
    56  				p.ExitNum = 1
    57  				return nil
    58  			}
    59  		} else {
    60  			// --- or ---
    61  			if (conditional && !p.IsNot) || (!conditional && p.IsNot) {
    62  				p.ExitNum = -1
    63  				return nil
    64  			}
    65  		}
    66  	}
    67  
    68  	if isAnd {
    69  		// --- and ---
    70  		p.ExitNum = -1
    71  		return nil
    72  	}
    73  
    74  	// --- or ---
    75  	p.ExitNum = 1
    76  	return nil
    77  }