incomplete implementation of 'os' module

This commit is contained in:
Daniel Kang 2019-01-17 16:52:30 -08:00
parent 552e9c01c5
commit a14f6ec1c0
4 changed files with 228 additions and 111 deletions

View file

@ -0,0 +1,11 @@
package stdmods
import "github.com/d5/tengo/objects"
func wrapError(err error) objects.Object {
if err == nil {
return objects.TrueValue
}
return &objects.Error{Value: &objects.String{Value: err.Error()}}
}

View file

@ -1,28 +1,21 @@
package stdmods
import (
"fmt"
"github.com/d5/tengo/objects"
)
// FuncAFRF transform a function of 'func(float64) float64' signature
// FuncAR transform a function of 'func()' signature
// into a user function object.
func FuncAFRF(fn func(float64) float64) *objects.UserFunction {
func FuncAR(fn func()) *objects.UserFunction {
return &objects.UserFunction{
Value: func(args ...objects.Object) (ret objects.Object, err error) {
if len(args) != 1 {
if len(args) != 0 {
return nil, objects.ErrWrongNumArguments
}
switch arg := args[0].(type) {
case *objects.Int:
return &objects.Float{Value: fn(float64(arg.Value))}, nil
case *objects.Float:
return &objects.Float{Value: fn(arg.Value)}, nil
default:
return nil, fmt.Errorf("invalid argument type: %s", arg.TypeName())
}
fn()
return objects.UndefinedValue, nil
},
}
}
@ -41,6 +34,44 @@ func FuncARF(fn func() float64) *objects.UserFunction {
}
}
// FuncARSs transform a function of 'func() []string' signature
// into a user function object.
func FuncARSs(fn func() []string) *objects.UserFunction {
return &objects.UserFunction{
Value: func(args ...objects.Object) (ret objects.Object, err error) {
if len(args) != 0 {
return nil, objects.ErrWrongNumArguments
}
arr := &objects.Array{}
for _, osArg := range fn() {
arr.Value = append(arr.Value, &objects.String{Value: osArg})
}
return arr, nil
},
}
}
// FuncAFRF transform a function of 'func(float64) float64' signature
// into a user function object.
func FuncAFRF(fn func(float64) float64) *objects.UserFunction {
return &objects.UserFunction{
Value: func(args ...objects.Object) (ret objects.Object, err error) {
if len(args) != 1 {
return nil, objects.ErrWrongNumArguments
}
f1, ok := objects.ToFloat64(args[0])
if !ok {
return nil, objects.ErrInvalidTypeConversion
}
return &objects.Float{Value: fn(f1)}, nil
},
}
}
// FuncAIRF transform a function of 'func(int) float64' signature
// into a user function object.
func FuncAIRF(fn func(int) float64) *objects.UserFunction {
@ -50,14 +81,12 @@ func FuncAIRF(fn func(int) float64) *objects.UserFunction {
return nil, objects.ErrWrongNumArguments
}
switch arg := args[0].(type) {
case *objects.Int:
return &objects.Float{Value: fn(int(arg.Value))}, nil
case *objects.Float:
return &objects.Float{Value: fn(int(arg.Value))}, nil
default:
return nil, fmt.Errorf("invalid argument type: %s", arg.TypeName())
i1, ok := objects.ToInt(args[0])
if !ok {
return nil, objects.ErrInvalidTypeConversion
}
return &objects.Float{Value: fn(i1)}, nil
},
}
}
@ -71,14 +100,12 @@ func FuncAFRI(fn func(float64) int) *objects.UserFunction {
return nil, objects.ErrWrongNumArguments
}
switch arg := args[0].(type) {
case *objects.Int:
return &objects.Int{Value: int64(fn(float64(arg.Value)))}, nil
case *objects.Float:
return &objects.Int{Value: int64(fn(arg.Value))}, nil
default:
return nil, fmt.Errorf("invalid argument type: %s", arg.TypeName())
f1, ok := objects.ToFloat64(args[0])
if !ok {
return nil, objects.ErrInvalidTypeConversion
}
return &objects.Int{Value: int64(fn(f1))}, nil
},
}
}
@ -92,26 +119,17 @@ func FuncAFFRF(fn func(float64, float64) float64) *objects.UserFunction {
return nil, objects.ErrWrongNumArguments
}
var arg0, arg1 float64
switch arg := args[0].(type) {
case *objects.Int:
arg0 = float64(arg.Value)
case *objects.Float:
arg0 = arg.Value
default:
return nil, fmt.Errorf("invalid argument type: %s", arg.TypeName())
}
switch arg := args[1].(type) {
case *objects.Int:
arg1 = float64(arg.Value)
case *objects.Float:
arg1 = arg.Value
default:
return nil, fmt.Errorf("invalid argument type: %s", arg.TypeName())
f1, ok := objects.ToFloat64(args[0])
if !ok {
return nil, objects.ErrInvalidTypeConversion
}
return &objects.Float{Value: fn(arg0, arg1)}, nil
f2, ok := objects.ToFloat64(args[1])
if !ok {
return nil, objects.ErrInvalidTypeConversion
}
return &objects.Float{Value: fn(f1, f2)}, nil
},
}
}
@ -125,27 +143,17 @@ func FuncAIFRF(fn func(int, float64) float64) *objects.UserFunction {
return nil, objects.ErrWrongNumArguments
}
var arg0 int
var arg1 float64
switch arg := args[0].(type) {
case *objects.Int:
arg0 = int(arg.Value)
case *objects.Float:
arg0 = int(arg.Value)
default:
return nil, fmt.Errorf("invalid argument type: %s", arg.TypeName())
}
switch arg := args[1].(type) {
case *objects.Int:
arg1 = float64(arg.Value)
case *objects.Float:
arg1 = arg.Value
default:
return nil, fmt.Errorf("invalid argument type: %s", arg.TypeName())
i1, ok := objects.ToInt(args[0])
if !ok {
return nil, objects.ErrInvalidTypeConversion
}
return &objects.Float{Value: fn(arg0, arg1)}, nil
f2, ok := objects.ToFloat64(args[1])
if !ok {
return nil, objects.ErrInvalidTypeConversion
}
return &objects.Float{Value: fn(i1, f2)}, nil
},
}
}
@ -159,27 +167,17 @@ func FuncAFIRF(fn func(float64, int) float64) *objects.UserFunction {
return nil, objects.ErrWrongNumArguments
}
var arg0 float64
var arg1 int
switch arg := args[0].(type) {
case *objects.Int:
arg0 = float64(arg.Value)
case *objects.Float:
arg0 = float64(arg.Value)
default:
return nil, fmt.Errorf("invalid argument type: %s", arg.TypeName())
}
switch arg := args[1].(type) {
case *objects.Int:
arg1 = int(arg.Value)
case *objects.Float:
arg1 = int(arg.Value)
default:
return nil, fmt.Errorf("invalid argument type: %s", arg.TypeName())
f1, ok := objects.ToFloat64(args[0])
if !ok {
return nil, objects.ErrInvalidTypeConversion
}
return &objects.Float{Value: fn(arg0, arg1)}, nil
i2, ok := objects.ToInt(args[1])
if !ok {
return nil, objects.ErrInvalidTypeConversion
}
return &objects.Float{Value: fn(f1, i2)}, nil
},
}
}
@ -193,27 +191,17 @@ func FuncAFIRB(fn func(float64, int) bool) *objects.UserFunction {
return nil, objects.ErrWrongNumArguments
}
var arg0 float64
var arg1 int
switch arg := args[0].(type) {
case *objects.Int:
arg0 = float64(arg.Value)
case *objects.Float:
arg0 = arg.Value
default:
return nil, fmt.Errorf("invalid argument type: %s", arg.TypeName())
}
switch arg := args[1].(type) {
case *objects.Int:
arg1 = int(arg.Value)
case *objects.Float:
arg1 = int(arg.Value)
default:
return nil, fmt.Errorf("invalid argument type: %s", arg.TypeName())
f1, ok := objects.ToFloat64(args[0])
if !ok {
return nil, objects.ErrInvalidTypeConversion
}
return &objects.Bool{Value: fn(arg0, arg1)}, nil
i2, ok := objects.ToInt(args[1])
if !ok {
return nil, objects.ErrInvalidTypeConversion
}
return &objects.Bool{Value: fn(f1, i2)}, nil
},
}
}
@ -227,17 +215,31 @@ func FuncAFRB(fn func(float64) bool) *objects.UserFunction {
return nil, objects.ErrWrongNumArguments
}
var arg0 float64
switch arg := args[0].(type) {
case *objects.Int:
arg0 = float64(arg.Value)
case *objects.Float:
arg0 = arg.Value
default:
return nil, fmt.Errorf("invalid argument type: %s", arg.TypeName())
f1, ok := objects.ToFloat64(args[0])
if !ok {
return nil, objects.ErrInvalidTypeConversion
}
return &objects.Bool{Value: fn(arg0)}, nil
return &objects.Bool{Value: fn(f1)}, nil
},
}
}
// FuncASRE transform a function of 'func(string) error' signature into a user function object.
// User function will return 'true' if underlying native function returns nil.
func FuncASRE(fn func(string) error) *objects.UserFunction {
return &objects.UserFunction{
Value: func(args ...objects.Object) (objects.Object, error) {
if len(args) != 1 {
return nil, objects.ErrWrongNumArguments
}
s1, ok := objects.ToString(args[0])
if !ok {
return nil, objects.ErrInvalidTypeConversion
}
return wrapError(fn(s1)), nil
},
}
}

103
compiler/stdmods/os.go Normal file
View file

@ -0,0 +1,103 @@
package stdmods
import (
"os"
"github.com/d5/tengo/objects"
)
var osModule = map[string]objects.Object{
"o_rdonly": &objects.Int{Value: int64(os.O_RDONLY)},
"o_wronly": &objects.Int{Value: int64(os.O_WRONLY)},
"o_rdwr": &objects.Int{Value: int64(os.O_RDWR)},
"o_append": &objects.Int{Value: int64(os.O_APPEND)},
"o_create": &objects.Int{Value: int64(os.O_CREATE)},
"o_excl": &objects.Int{Value: int64(os.O_EXCL)},
"o_sync": &objects.Int{Value: int64(os.O_SYNC)},
"o_trunc": &objects.Int{Value: int64(os.O_TRUNC)},
"mode_dir": &objects.Int{Value: int64(os.ModeDir)},
"mode_append": &objects.Int{Value: int64(os.ModeAppend)},
"mode_exclusive": &objects.Int{Value: int64(os.ModeExclusive)},
"mode_temporary": &objects.Int{Value: int64(os.ModeTemporary)},
"mode_symlink": &objects.Int{Value: int64(os.ModeSymlink)},
"mode_device": &objects.Int{Value: int64(os.ModeDevice)},
"mode_named_pipe": &objects.Int{Value: int64(os.ModeNamedPipe)},
"mode_socket": &objects.Int{Value: int64(os.ModeSocket)},
"mode_setuid": &objects.Int{Value: int64(os.ModeSetuid)},
"mode_setgui": &objects.Int{Value: int64(os.ModeSetgid)},
"mode_char_device": &objects.Int{Value: int64(os.ModeCharDevice)},
"mode_sticky": &objects.Int{Value: int64(os.ModeSticky)},
"mode_irregular": &objects.Int{Value: int64(os.ModeIrregular)},
"mode_type": &objects.Int{Value: int64(os.ModeType)},
"mode_perm": &objects.Int{Value: int64(os.ModePerm)},
"path_separator": &objects.Char{Value: os.PathSeparator},
"path_list_separator": &objects.Char{Value: os.PathListSeparator},
"dev_null": &objects.String{Value: os.DevNull},
"args": &objects.UserFunction{Value: osArgs},
"chdir": FuncASRE(os.Chdir),
"chmod": &objects.UserFunction{Value: osChmod},
"chown": &objects.UserFunction{Value: osChown},
"clearenv": FuncAR(os.Clearenv),
"environ": FuncARSs(os.Environ),
// TODO: system errors
//"err_invalid": &objects.Error{Value: os.ErrInvalid.Error()},
// TODO: STDIN, STDOUT, STDERR
// "stdin": nil,
// "stdout": nil,
// "stderr": nil,
}
func osArgs(args ...objects.Object) (objects.Object, error) {
if len(args) != 0 {
return nil, objects.ErrWrongNumArguments
}
arr := &objects.Array{}
for _, osArg := range os.Args {
arr.Value = append(arr.Value, &objects.String{Value: osArg})
}
return arr, nil
}
func osChmod(args ...objects.Object) (objects.Object, error) {
if len(args) != 2 {
return nil, objects.ErrWrongNumArguments
}
s1, ok := objects.ToString(args[0])
if !ok {
return nil, objects.ErrInvalidTypeConversion
}
i2, ok := objects.ToInt(args[1])
if !ok {
return nil, objects.ErrInvalidTypeConversion
}
return wrapError(os.Chmod(s1, os.FileMode(i2))), nil
}
func osChown(args ...objects.Object) (objects.Object, error) {
if len(args) != 3 {
return nil, objects.ErrWrongNumArguments
}
s1, ok := objects.ToString(args[0])
if !ok {
return nil, objects.ErrInvalidTypeConversion
}
i2, ok := objects.ToInt(args[1])
if !ok {
return nil, objects.ErrInvalidTypeConversion
}
i3, ok := objects.ToInt(args[2])
if !ok {
return nil, objects.ErrInvalidTypeConversion
}
return wrapError(os.Chown(s1, i2, i3)), nil
}

View file

@ -5,4 +5,5 @@ import "github.com/d5/tengo/objects"
// Modules contain the standard modules.
var Modules = map[string]*objects.ModuleMap{
"math": {Value: mathModule},
"os": {Value: osModule},
}