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

     1  package structs
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"io"
     7  
     8  	"github.com/lmorg/murex/lang"
     9  	"github.com/lmorg/murex/lang/runmode"
    10  	"github.com/lmorg/murex/lang/types"
    11  )
    12  
    13  func init() {
    14  	lang.DefineFunction("runmode", cmdRunmode, types.Null)
    15  
    16  	lang.DefineFunction("unsafe", cmdUnsafe, types.Any)
    17  	lang.DefineFunction("try", cmdTry, types.Any)
    18  	lang.DefineFunction("trypipe", cmdTryPipe, types.Any)
    19  	lang.DefineFunction("tryerr", cmdTryErr, types.Any)
    20  	lang.DefineFunction("trypipeerr", cmdTryPipeErr, types.Any)
    21  
    22  	lang.DefineFunction("catch", cmdCatch, types.Any)
    23  	lang.DefineFunction("!catch", cmdCatch, types.Any)
    24  }
    25  
    26  func cmdRunmode(p *lang.Process) error {
    27  	p.Stdout.SetDataType(types.Null)
    28  	return errors.New("`runmode` should only be used as the first statement in a block")
    29  }
    30  
    31  func cmdTry(p *lang.Process) error        { return tryModes(p, runmode.BlockTry) }
    32  func cmdTryPipe(p *lang.Process) error    { return tryModes(p, runmode.BlockTryPipe) }
    33  func cmdTryErr(p *lang.Process) error     { return tryModes(p, runmode.BlockTryErr) }
    34  func cmdTryPipeErr(p *lang.Process) error { return tryModes(p, runmode.BlockTryPipeErr) }
    35  
    36  func tryModes(p *lang.Process, runMode runmode.RunMode) (err error) {
    37  	p.Stdout.SetDataType(types.Null)
    38  
    39  	block, err := p.Parameters.String(0)
    40  	if err != nil {
    41  		return err
    42  	}
    43  
    44  	r := []rune(block)
    45  	if types.IsBlockRune(r) {
    46  		p.RunMode = runMode
    47  		p.ExitNum, err = p.Fork(lang.F_PARENT_VARTABLE).Execute(r)
    48  		return
    49  	}
    50  
    51  	return fmt.Errorf("unexpected parameter '%s', expecting a code block inside curly braces", block)
    52  }
    53  
    54  func cmdUnsafe(p *lang.Process) error {
    55  	p.Stdout.SetDataType(types.Null)
    56  
    57  	block, err := p.Parameters.String(0)
    58  	if err != nil {
    59  		return err
    60  	}
    61  
    62  	r := []rune(block)
    63  	if types.IsBlockRune(r) {
    64  		p.RunMode = runmode.BlockUnsafe
    65  		p.ExitNum, err = p.Fork(lang.F_PARENT_VARTABLE).Execute(r)
    66  		if err != nil {
    67  			p.Stderr.Writeln([]byte(err.Error()))
    68  		}
    69  		return nil
    70  	}
    71  
    72  	return fmt.Errorf("unexpected parameter '%s', expecting a code block inside curly braces", block)
    73  }
    74  
    75  func cmdCatch(p *lang.Process) error {
    76  	p.Stdout.SetDataType(types.Generic)
    77  
    78  	block, err := p.Parameters.Block(0)
    79  	if err != nil {
    80  		return err
    81  	}
    82  
    83  	_, err = io.Copy(p.Stdout, p.Stdin)
    84  	if err != nil {
    85  		return err
    86  	}
    87  
    88  	p.ExitNum = p.Previous.ExitNum
    89  
    90  	if p.Previous.ExitNum != 0 && !p.IsNot {
    91  		_, err = p.Fork(lang.F_PARENT_VARTABLE | lang.F_NO_STDIN).Execute(block)
    92  		if err != nil {
    93  			return err
    94  		}
    95  
    96  	} else if p.Previous.ExitNum == 0 && p.IsNot {
    97  		_, err = p.Fork(lang.F_PARENT_VARTABLE | lang.F_NO_STDIN).Execute(block)
    98  		if err != nil {
    99  			return err
   100  		}
   101  	}
   102  
   103  	return nil
   104  }