github.com/lmorg/murex@v0.0.0-20240217211045-e081c89cd4ef/builtins/core/management/fexec.go (about) 1 package management 2 3 import ( 4 "fmt" 5 "strings" 6 7 "github.com/lmorg/murex/lang" 8 "github.com/lmorg/murex/lang/ref" 9 "github.com/lmorg/murex/lang/types" 10 "github.com/lmorg/murex/utils/json" 11 ) 12 13 type feType struct { 14 fn func(*lang.Process, string, []string) error 15 desc string 16 } 17 18 var fe map[string]feType 19 20 func init() { 21 lang.DefineFunction("fexec", cmdFexec, types.Any) 22 23 fe = map[string]feType{ 24 "function": { 25 desc: "Execute a murex public function", 26 fn: feFunction, 27 }, 28 29 "private": { 30 desc: "Execute a murex private function", 31 fn: fePrivate, 32 }, 33 34 /*"event": { 35 desc: "event", 36 fn: func(p *lang.Process, cmd string, params []string) error { 37 return fmt.Errorf("TODO: function not written yet") 38 }, 39 },*/ 40 41 "builtin": { 42 desc: "Execute a murex builtin", 43 fn: feBuiltin, 44 }, 45 46 "help": { 47 desc: "Display help message", 48 fn: feHelp, 49 }, 50 } 51 52 } 53 54 func cmdFexec(p *lang.Process) error { 55 flag, err := p.Parameters.String(0) 56 if err != nil { 57 return err 58 } 59 60 if fe[flag].fn == nil { 61 return fmt.Errorf("invalid flag '%s'. Use 'help' for more help", flag) 62 } 63 64 cmd, err := p.Parameters.String(1) 65 if err != nil && flag != "help" { 66 return err 67 } 68 69 var params []string 70 if p.Parameters.Len() > 2 { 71 params = p.Parameters.StringArray()[2:] 72 } 73 74 return fe[flag].fn(p, cmd, params) 75 } 76 77 func feBlock(p *lang.Process, block []rune, cmd string, params []string, fileRef *ref.File) (err error) { 78 fork := p.Fork(lang.F_FUNCTION) 79 fork.Name.Set(cmd) 80 fork.Parameters.DefineParsed(params) 81 fork.FileRef = fileRef 82 p.ExitNum, err = fork.Execute(block) 83 return 84 } 85 86 func feFunction(p *lang.Process, cmd string, params []string) error { 87 block, err := lang.MxFunctions.Block(cmd) 88 if err != nil { 89 return err 90 } 91 92 return feBlock(p, block, cmd, params, p.FileRef) 93 } 94 95 func fePrivate(p *lang.Process, cmd string, params []string) error { 96 mod := strings.Split(cmd, "/") 97 if len(mod) > 1 && mod[0] == "" { 98 mod = mod[1:] 99 } 100 101 switch len(mod) { 102 case 0, 1: 103 mod = []string{"", cmd} 104 105 case 2: 106 // do nothing 107 108 default: 109 mod = []string{strings.Join(mod[0:len(mod)-1], "/"), mod[2]} 110 } 111 112 pvt := lang.PrivateFunctions.GetString(mod[1], mod[0]) 113 if pvt == nil { 114 return lang.ErrPrivateNotFound(mod[0]) 115 } 116 117 return feBlock(p, pvt.Block, mod[1], params, pvt.FileRef) 118 } 119 120 func feBuiltin(p *lang.Process, cmd string, params []string) error { 121 if lang.GoFunctions[cmd] == nil { 122 return fmt.Errorf("no builtin exists with the name `%s`", cmd) 123 } 124 125 fork := p.Fork(lang.F_DEFAULTS) 126 fork.Name.Set(cmd) 127 fork.Parameters.DefineParsed(params) 128 fork.FileRef = p.FileRef 129 return lang.GoFunctions[cmd](fork.Process) 130 } 131 132 func feHelp(p *lang.Process, _ string, _ []string) error { 133 p.Stdout.SetDataType(types.Json) 134 135 v := make(map[string]string) 136 137 for name := range fe { 138 v[name] = fe[name].desc 139 } 140 141 b, err := json.Marshal(v, p.Stdout.IsTTY()) 142 if err != nil { 143 return err 144 } 145 146 _, err = p.Stdout.Write(b) 147 return err 148 }