From b5108b8065f4eeb9461e2dbc9ddcab8ccc01f0e9 Mon Sep 17 00:00:00 2001 From: Daniel Kang Date: Fri, 18 Jan 2019 02:28:58 -0800 Subject: [PATCH] os Process functions --- compiler/stdlib/func_typedefs.go | 14 ++++ compiler/stdlib/os.go | 7 ++ compiler/stdlib/os_process.go | 129 +++++++++++++++++++++++++++++++ 3 files changed, 150 insertions(+) create mode 100644 compiler/stdlib/os_process.go diff --git a/compiler/stdlib/func_typedefs.go b/compiler/stdlib/func_typedefs.go index 83c540f..022c77f 100644 --- a/compiler/stdlib/func_typedefs.go +++ b/compiler/stdlib/func_typedefs.go @@ -34,6 +34,20 @@ func FuncARI(fn func() int) *objects.UserFunction { } } +// FuncARB transform a function of 'func() bool' signature +// into a user function object. +func FuncARB(fn func() bool) *objects.UserFunction { + return &objects.UserFunction{ + Value: func(args ...objects.Object) (ret objects.Object, err error) { + if len(args) != 0 { + return nil, objects.ErrWrongNumArguments + } + + return &objects.Bool{Value: fn()}, nil + }, + } +} + // FuncARE transform a function of 'func() error' signature // into a user function object. func FuncARE(fn func() error) *objects.UserFunction { diff --git a/compiler/stdlib/os.go b/compiler/stdlib/os.go index 06aa1d9..660594d 100644 --- a/compiler/stdlib/os.go +++ b/compiler/stdlib/os.go @@ -33,6 +33,9 @@ var osModule = map[string]objects.Object{ "path_separator": &objects.Char{Value: os.PathSeparator}, "path_list_separator": &objects.Char{Value: os.PathListSeparator}, "dev_null": &objects.String{Value: os.DevNull}, + "seek_set": &objects.Int{Value: int64(os.SEEK_SET)}, + "seek_cur": &objects.Int{Value: int64(os.SEEK_CUR)}, + "seek_end": &objects.Int{Value: int64(os.SEEK_END)}, // args() => array(string) "args": &objects.UserFunction{Value: osArgs}, // chdir(dir string) => error @@ -109,6 +112,10 @@ var osModule = map[string]objects.Object{ "open": &objects.UserFunction{Value: osOpen}, // open_file(name string, flag int, perm int) => imap(file)/error "open_file": &objects.UserFunction{Value: osOpenFile}, + // find_process(pid int) => imap(process)/error + "find_process": &objects.UserFunction{Value: osFindProcess}, + // start_process(name string, argv array(string), dir string, env array(string)) => imap(process)/error + "start_process": &objects.UserFunction{Value: osStartProcess}, // TODO: implemented more functions //"stdin": nil, diff --git a/compiler/stdlib/os_process.go b/compiler/stdlib/os_process.go new file mode 100644 index 0000000..45872d7 --- /dev/null +++ b/compiler/stdlib/os_process.go @@ -0,0 +1,129 @@ +package stdlib + +import ( + "os" + "syscall" + + "github.com/d5/tengo/objects" +) + +func osProcessStateImmutableMap(state *os.ProcessState) *objects.ImmutableMap { + return &objects.ImmutableMap{ + Value: map[string]objects.Object{ + "exited": FuncARB(state.Exited), + "pid": FuncARI(state.Pid), + "string": FuncARS(state.String), + "success": FuncARB(state.Success), + }, + } +} + +func osProcessImmutableMap(proc *os.Process) *objects.ImmutableMap { + return &objects.ImmutableMap{ + Value: map[string]objects.Object{ + "kill": FuncARE(proc.Kill), + "release": FuncARE(proc.Release), + "signal": &objects.UserFunction{ + Value: func(args ...objects.Object) (ret objects.Object, err error) { + if len(args) != 1 { + return nil, objects.ErrWrongNumArguments + } + + i1, ok := objects.ToInt64(args[0]) + if !ok { + return nil, objects.ErrInvalidTypeConversion + } + + return wrapError(proc.Signal(syscall.Signal(i1))), nil + }, + }, + "wait": &objects.UserFunction{ + Value: func(args ...objects.Object) (ret objects.Object, err error) { + if len(args) != 0 { + return nil, objects.ErrWrongNumArguments + } + + state, err := proc.Wait() + if err != nil { + return wrapError(err), nil + } + + return osProcessStateImmutableMap(state), nil + }, + }, + }, + } +} + +func osFindProcess(args ...objects.Object) (objects.Object, error) { + if len(args) != 1 { + return nil, objects.ErrWrongNumArguments + } + + i1, ok := objects.ToInt(args[0]) + if !ok { + return nil, objects.ErrInvalidTypeConversion + } + + proc, err := os.FindProcess(i1) + if err != nil { + return wrapError(err), nil + } + + return osProcessImmutableMap(proc), nil +} + +func osStartProcess(args ...objects.Object) (objects.Object, error) { + if len(args) != 4 { + return nil, objects.ErrWrongNumArguments + } + + name, ok := objects.ToString(args[0]) + if !ok { + return nil, objects.ErrInvalidTypeConversion + } + + argv, err := stringArray(args[1]) + if err != nil { + return nil, err + } + + dir, ok := objects.ToString(args[2]) + if !ok { + return nil, objects.ErrInvalidTypeConversion + } + + env, err := stringArray(args[3]) + if err != nil { + return nil, err + } + + proc, err := os.StartProcess(name, argv, &os.ProcAttr{ + Dir: dir, + Env: env, + }) + if err != nil { + return wrapError(err), nil + } + + return osProcessImmutableMap(proc), nil +} + +func stringArray(o objects.Object) ([]string, error) { + arr, ok := o.(*objects.Array) + if !ok { + return nil, objects.ErrInvalidTypeConversion + } + + var sarr []string + for _, elem := range arr.Value { + str, ok := elem.(*objects.String) + if !ok { + return nil, objects.ErrInvalidTypeConversion + } + + sarr = append(sarr, str.Value) + } + + return sarr, nil +}