incomplete implementation of 'os' module
This commit is contained in:
parent
552e9c01c5
commit
a14f6ec1c0
4 changed files with 228 additions and 111 deletions
11
compiler/stdmods/errors.go
Normal file
11
compiler/stdmods/errors.go
Normal 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()}}
|
||||
}
|
|
@ -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
103
compiler/stdmods/os.go
Normal 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
|
||||
}
|
|
@ -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},
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue