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 }