add 'rand' module (#90)

This commit is contained in:
Daniel 2019-02-09 12:33:35 -08:00 committed by GitHub
parent 9782d87c35
commit 2b517f376e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 344 additions and 54 deletions

View file

@ -34,6 +34,60 @@ func FuncARI(fn func() int) *objects.UserFunction {
}
}
// FuncARI64 transform a function of 'func() int64' signature
// into a user function object.
func FuncARI64(fn func() int64) *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.Int{Value: fn()}, nil
},
}
}
// FuncAI64RI64 transform a function of 'func(int64) int64' signature
// into a user function object.
func FuncAI64RI64(fn func(int64) int64) *objects.UserFunction {
return &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 &objects.Int{Value: fn(i1)}, nil
},
}
}
// FuncAI64R transform a function of 'func(int64)' signature
// into a user function object.
func FuncAI64R(fn func(int64)) *objects.UserFunction {
return &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
}
fn(i1)
return objects.UndefinedValue, nil
},
}
}
// FuncARB transform a function of 'func() bool' signature
// into a user function object.
func FuncARB(fn func() bool) *objects.UserFunction {
@ -175,6 +229,32 @@ func FuncARIsE(fn func() ([]int, error)) *objects.UserFunction {
}
}
// FuncAIRIs transform a function of 'func(int) []int' signature
// into a user function object.
func FuncAIRIs(fn func(int) []int) *objects.UserFunction {
return &objects.UserFunction{
Value: func(args ...objects.Object) (ret objects.Object, err error) {
if len(args) != 1 {
return nil, objects.ErrWrongNumArguments
}
i1, ok := objects.ToInt(args[0])
if !ok {
return nil, objects.ErrInvalidTypeConversion
}
res := fn(i1)
arr := &objects.Array{}
for _, v := range res {
arr.Value = append(arr.Value, &objects.Int{Value: int64(v)})
}
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 {

View file

@ -16,7 +16,7 @@ func TestFuncAIR(t *testing.T) {
ret, err := uf.Call(&objects.Int{Value: 10})
assert.NoError(t, err)
assert.Equal(t, objects.UndefinedValue, ret)
ret, err = uf.Call()
_, err = uf.Call()
assert.Equal(t, objects.ErrWrongNumArguments, err)
}
@ -25,7 +25,7 @@ func TestFuncAR(t *testing.T) {
ret, err := uf.Call()
assert.NoError(t, err)
assert.Equal(t, objects.UndefinedValue, ret)
ret, err = uf.Call(objects.TrueValue)
_, err = uf.Call(objects.TrueValue)
assert.Equal(t, objects.ErrWrongNumArguments, err)
}
@ -34,7 +34,7 @@ func TestFuncARI(t *testing.T) {
ret, err := uf.Call()
assert.NoError(t, err)
assert.Equal(t, &objects.Int{Value: 10}, ret)
ret, err = uf.Call(objects.TrueValue)
_, err = uf.Call(objects.TrueValue)
assert.Equal(t, objects.ErrWrongNumArguments, err)
}
@ -47,7 +47,7 @@ func TestFuncARE(t *testing.T) {
ret, err = uf.Call()
assert.NoError(t, err)
assert.Equal(t, &objects.Error{Value: &objects.String{Value: "some error"}}, ret)
ret, err = uf.Call(objects.TrueValue)
_, err = uf.Call(objects.TrueValue)
assert.Equal(t, objects.ErrWrongNumArguments, err)
}
@ -60,7 +60,7 @@ func TestFuncARIsE(t *testing.T) {
ret, err = uf.Call()
assert.NoError(t, err)
assert.Equal(t, &objects.Error{Value: &objects.String{Value: "some error"}}, ret)
ret, err = uf.Call(objects.TrueValue)
_, err = uf.Call(objects.TrueValue)
assert.Equal(t, objects.ErrWrongNumArguments, err)
}
@ -69,7 +69,7 @@ func TestFuncARS(t *testing.T) {
ret, err := uf.Call()
assert.NoError(t, err)
assert.Equal(t, &objects.String{Value: "foo"}, ret)
ret, err = uf.Call(objects.TrueValue)
_, err = uf.Call(objects.TrueValue)
assert.Equal(t, objects.ErrWrongNumArguments, err)
}
@ -82,7 +82,7 @@ func TestFuncARSE(t *testing.T) {
ret, err = uf.Call()
assert.NoError(t, err)
assert.Equal(t, &objects.Error{Value: &objects.String{Value: "some error"}}, ret)
ret, err = uf.Call(objects.TrueValue)
_, err = uf.Call(objects.TrueValue)
assert.Equal(t, objects.ErrWrongNumArguments, err)
}
@ -91,7 +91,7 @@ func TestFuncARSs(t *testing.T) {
ret, err := uf.Call()
assert.NoError(t, err)
assert.Equal(t, array(&objects.String{Value: "foo"}, &objects.String{Value: "bar"}), ret)
ret, err = uf.Call(objects.TrueValue)
_, err = uf.Call(objects.TrueValue)
assert.Equal(t, objects.ErrWrongNumArguments, err)
}
@ -104,7 +104,7 @@ func TestFuncASRE(t *testing.T) {
ret, err = uf.Call(&objects.String{Value: "foo"})
assert.NoError(t, err)
assert.Equal(t, &objects.Error{Value: &objects.String{Value: "some error"}}, ret)
ret, err = uf.Call()
_, err = uf.Call()
assert.Equal(t, objects.ErrWrongNumArguments, err)
}
@ -113,7 +113,7 @@ func TestFuncASRS(t *testing.T) {
ret, err := uf.Call(&objects.String{Value: "foo"})
assert.NoError(t, err)
assert.Equal(t, &objects.String{Value: "foo"}, ret)
ret, err = uf.Call()
_, err = uf.Call()
assert.Equal(t, objects.ErrWrongNumArguments, err)
}
@ -122,7 +122,7 @@ func TestFuncASRSs(t *testing.T) {
ret, err := uf.Call(&objects.String{Value: "foo"})
assert.NoError(t, err)
assert.Equal(t, array(&objects.String{Value: "foo"}), ret)
ret, err = uf.Call()
_, err = uf.Call()
assert.Equal(t, objects.ErrWrongNumArguments, err)
}
@ -135,7 +135,7 @@ func TestFuncASI64RE(t *testing.T) {
ret, err = uf.Call(&objects.String{Value: "foo"}, &objects.Int{Value: 5})
assert.NoError(t, err)
assert.Equal(t, &objects.Error{Value: &objects.String{Value: "some error"}}, ret)
ret, err = uf.Call()
_, err = uf.Call()
assert.Equal(t, objects.ErrWrongNumArguments, err)
}
@ -148,7 +148,7 @@ func TestFuncAIIRE(t *testing.T) {
ret, err = uf.Call(&objects.Int{Value: 5}, &objects.Int{Value: 7})
assert.NoError(t, err)
assert.Equal(t, &objects.Error{Value: &objects.String{Value: "some error"}}, ret)
ret, err = uf.Call()
_, err = uf.Call()
assert.Equal(t, objects.ErrWrongNumArguments, err)
}
@ -161,7 +161,7 @@ func TestFuncASIIRE(t *testing.T) {
ret, err = uf.Call(&objects.String{Value: "foo"}, &objects.Int{Value: 5}, &objects.Int{Value: 7})
assert.NoError(t, err)
assert.Equal(t, &objects.Error{Value: &objects.String{Value: "some error"}}, ret)
ret, err = uf.Call()
_, err = uf.Call()
assert.Equal(t, objects.ErrWrongNumArguments, err)
}
@ -174,7 +174,7 @@ func TestFuncASRSE(t *testing.T) {
ret, err = uf.Call(&objects.String{Value: "foo"})
assert.NoError(t, err)
assert.Equal(t, &objects.Error{Value: &objects.String{Value: "some error"}}, ret)
ret, err = uf.Call()
_, err = uf.Call()
assert.Equal(t, objects.ErrWrongNumArguments, err)
}
@ -186,7 +186,7 @@ func TestFuncASSRE(t *testing.T) {
ret, err = uf.Call(&objects.String{Value: "foo"}, &objects.String{Value: "bar"})
assert.NoError(t, err)
assert.Equal(t, &objects.Error{Value: &objects.String{Value: "some error"}}, ret)
ret, err = uf.Call(&objects.String{Value: "foo"})
_, err = uf.Call(&objects.String{Value: "foo"})
assert.Equal(t, objects.ErrWrongNumArguments, err)
}
@ -195,31 +195,27 @@ func TestFuncASsRS(t *testing.T) {
ret, err := uf.Call(array(&objects.String{Value: "foo"}, &objects.String{Value: "bar"}), &objects.String{Value: " "})
assert.NoError(t, err)
assert.Equal(t, &objects.String{Value: "foo bar"}, ret)
ret, err = uf.Call(&objects.String{Value: "foo"})
_, err = uf.Call(&objects.String{Value: "foo"})
assert.Equal(t, objects.ErrWrongNumArguments, err)
}
func TestFuncARF(t *testing.T) {
uf := stdlib.FuncARF(func() float64 {
return 10.0
})
uf := stdlib.FuncARF(func() float64 { return 10.0 })
ret, err := uf.Call()
assert.NoError(t, err)
assert.Equal(t, &objects.Float{Value: 10.0}, ret)
ret, err = uf.Call(objects.TrueValue)
_, err = uf.Call(objects.TrueValue)
assert.Equal(t, objects.ErrWrongNumArguments, err)
}
func TestFuncAFRF(t *testing.T) {
uf := stdlib.FuncAFRF(func(a float64) float64 {
return a
})
uf := stdlib.FuncAFRF(func(a float64) float64 { return a })
ret, err := uf.Call(&objects.Float{Value: 10.0})
assert.NoError(t, err)
assert.Equal(t, &objects.Float{Value: 10.0}, ret)
ret, err = uf.Call()
_, err = uf.Call()
assert.Equal(t, objects.ErrWrongNumArguments, err)
ret, err = uf.Call(objects.TrueValue, objects.TrueValue)
_, err = uf.Call(objects.TrueValue, objects.TrueValue)
assert.Equal(t, objects.ErrWrongNumArguments, err)
}
@ -230,9 +226,9 @@ func TestFuncAIRF(t *testing.T) {
ret, err := uf.Call(&objects.Int{Value: 10.0})
assert.NoError(t, err)
assert.Equal(t, &objects.Float{Value: 10.0}, ret)
ret, err = uf.Call()
_, err = uf.Call()
assert.Equal(t, objects.ErrWrongNumArguments, err)
ret, err = uf.Call(objects.TrueValue, objects.TrueValue)
_, err = uf.Call(objects.TrueValue, objects.TrueValue)
assert.Equal(t, objects.ErrWrongNumArguments, err)
}
@ -243,9 +239,9 @@ func TestFuncAFRI(t *testing.T) {
ret, err := uf.Call(&objects.Float{Value: 10.5})
assert.NoError(t, err)
assert.Equal(t, &objects.Int{Value: 10}, ret)
ret, err = uf.Call()
_, err = uf.Call()
assert.Equal(t, objects.ErrWrongNumArguments, err)
ret, err = uf.Call(objects.TrueValue, objects.TrueValue)
_, err = uf.Call(objects.TrueValue, objects.TrueValue)
assert.Equal(t, objects.ErrWrongNumArguments, err)
}
@ -256,9 +252,9 @@ func TestFuncAFRB(t *testing.T) {
ret, err := uf.Call(&objects.Float{Value: 0.1})
assert.NoError(t, err)
assert.Equal(t, objects.TrueValue, ret)
ret, err = uf.Call()
_, err = uf.Call()
assert.Equal(t, objects.ErrWrongNumArguments, err)
ret, err = uf.Call(objects.TrueValue, objects.TrueValue)
_, err = uf.Call(objects.TrueValue, objects.TrueValue)
assert.Equal(t, objects.ErrWrongNumArguments, err)
}
@ -269,9 +265,9 @@ func TestFuncAFFRF(t *testing.T) {
ret, err := uf.Call(&objects.Float{Value: 10.0}, &objects.Float{Value: 20.0})
assert.NoError(t, err)
assert.Equal(t, &objects.Float{Value: 30.0}, ret)
ret, err = uf.Call()
_, err = uf.Call()
assert.Equal(t, objects.ErrWrongNumArguments, err)
ret, err = uf.Call(objects.TrueValue)
_, err = uf.Call(objects.TrueValue)
assert.Equal(t, objects.ErrWrongNumArguments, err)
}
@ -280,9 +276,9 @@ func TestFuncASIRS(t *testing.T) {
ret, err := uf.Call(&objects.String{Value: "ab"}, &objects.Int{Value: 2})
assert.NoError(t, err)
assert.Equal(t, &objects.String{Value: "abab"}, ret)
ret, err = uf.Call()
_, err = uf.Call()
assert.Equal(t, objects.ErrWrongNumArguments, err)
ret, err = uf.Call(objects.TrueValue)
_, err = uf.Call(objects.TrueValue)
assert.Equal(t, objects.ErrWrongNumArguments, err)
}
@ -293,9 +289,9 @@ func TestFuncAIFRF(t *testing.T) {
ret, err := uf.Call(&objects.Int{Value: 10}, &objects.Float{Value: 20.0})
assert.NoError(t, err)
assert.Equal(t, &objects.Float{Value: 30.0}, ret)
ret, err = uf.Call()
_, err = uf.Call()
assert.Equal(t, objects.ErrWrongNumArguments, err)
ret, err = uf.Call(objects.TrueValue)
_, err = uf.Call(objects.TrueValue)
assert.Equal(t, objects.ErrWrongNumArguments, err)
}
@ -306,9 +302,9 @@ func TestFuncAFIRF(t *testing.T) {
ret, err := uf.Call(&objects.Float{Value: 10.0}, &objects.Int{Value: 20})
assert.NoError(t, err)
assert.Equal(t, &objects.Float{Value: 30.0}, ret)
ret, err = uf.Call()
_, err = uf.Call()
assert.Equal(t, objects.ErrWrongNumArguments, err)
ret, err = uf.Call(objects.TrueValue)
_, err = uf.Call(objects.TrueValue)
assert.Equal(t, objects.ErrWrongNumArguments, err)
}
@ -319,9 +315,9 @@ func TestFuncAFIRB(t *testing.T) {
ret, err := uf.Call(&objects.Float{Value: 10.0}, &objects.Int{Value: 20})
assert.NoError(t, err)
assert.Equal(t, objects.TrueValue, ret)
ret, err = uf.Call()
_, err = uf.Call()
assert.Equal(t, objects.ErrWrongNumArguments, err)
ret, err = uf.Call(objects.TrueValue)
_, err = uf.Call(objects.TrueValue)
assert.Equal(t, objects.ErrWrongNumArguments, err)
}
@ -338,7 +334,7 @@ func TestFuncAIRSsE(t *testing.T) {
ret, err = uf.Call(&objects.Int{Value: 10})
assert.NoError(t, err)
assert.Equal(t, &objects.Error{Value: &objects.String{Value: "some error"}}, ret)
ret, err = uf.Call()
_, err = uf.Call()
assert.Equal(t, objects.ErrWrongNumArguments, err)
}
@ -347,7 +343,7 @@ func TestFuncASSRSs(t *testing.T) {
ret, err := uf.Call(&objects.String{Value: "foo"}, &objects.String{Value: "bar"})
assert.NoError(t, err)
assert.Equal(t, array(&objects.String{Value: "foo"}, &objects.String{Value: "bar"}), ret)
ret, err = uf.Call()
_, err = uf.Call()
assert.Equal(t, objects.ErrWrongNumArguments, err)
}
@ -356,7 +352,7 @@ func TestFuncASSIRSs(t *testing.T) {
ret, err := uf.Call(&objects.String{Value: "foo"}, &objects.String{Value: "bar"}, &objects.Int{Value: 5})
assert.NoError(t, err)
assert.Equal(t, array(&objects.String{Value: "foo"}, &objects.String{Value: "bar"}, &objects.String{Value: "5"}), ret)
ret, err = uf.Call()
_, err = uf.Call()
assert.Equal(t, objects.ErrWrongNumArguments, err)
}
@ -365,7 +361,7 @@ func TestFuncARB(t *testing.T) {
ret, err := uf.Call()
assert.NoError(t, err)
assert.Equal(t, objects.TrueValue, ret)
ret, err = uf.Call(objects.TrueValue)
_, err = uf.Call(objects.TrueValue)
assert.Equal(t, objects.ErrWrongNumArguments, err)
}
@ -382,7 +378,7 @@ func TestFuncARYE(t *testing.T) {
ret, err = uf.Call()
assert.NoError(t, err)
assert.Equal(t, &objects.Error{Value: &objects.String{Value: "some error"}}, ret)
ret, err = uf.Call(objects.TrueValue)
_, err = uf.Call(objects.TrueValue)
assert.Equal(t, objects.ErrWrongNumArguments, err)
}
@ -395,7 +391,7 @@ func TestFuncASRIE(t *testing.T) {
ret, err = uf.Call(&objects.String{Value: "foo"})
assert.NoError(t, err)
assert.Equal(t, &objects.Error{Value: &objects.String{Value: "some error"}}, ret)
ret, err = uf.Call()
_, err = uf.Call()
assert.Equal(t, objects.ErrWrongNumArguments, err)
}
@ -408,7 +404,7 @@ func TestFuncAYRIE(t *testing.T) {
ret, err = uf.Call(&objects.Bytes{Value: []byte("foo")})
assert.NoError(t, err)
assert.Equal(t, &objects.Error{Value: &objects.String{Value: "some error"}}, ret)
ret, err = uf.Call()
_, err = uf.Call()
assert.Equal(t, objects.ErrWrongNumArguments, err)
}
@ -417,7 +413,7 @@ func TestFuncASSRI(t *testing.T) {
ret, err := uf.Call(&objects.String{Value: "foo"}, &objects.String{Value: "bar"})
assert.NoError(t, err)
assert.Equal(t, &objects.Int{Value: 6}, ret)
ret, err = uf.Call(&objects.String{Value: "foo"})
_, err = uf.Call(&objects.String{Value: "foo"})
assert.Equal(t, objects.ErrWrongNumArguments, err)
}
@ -426,7 +422,7 @@ func TestFuncASSRS(t *testing.T) {
ret, err := uf.Call(&objects.String{Value: "foo"}, &objects.String{Value: "bar"})
assert.NoError(t, err)
assert.Equal(t, &objects.String{Value: "foobar"}, ret)
ret, err = uf.Call(&objects.String{Value: "foo"})
_, err = uf.Call(&objects.String{Value: "foo"})
assert.Equal(t, objects.ErrWrongNumArguments, err)
}
@ -435,7 +431,7 @@ func TestFuncASSRB(t *testing.T) {
ret, err := uf.Call(&objects.String{Value: "123"}, &objects.String{Value: "12"})
assert.NoError(t, err)
assert.Equal(t, objects.TrueValue, ret)
ret, err = uf.Call(&objects.String{Value: "foo"})
_, err = uf.Call(&objects.String{Value: "foo"})
assert.Equal(t, objects.ErrWrongNumArguments, err)
}
@ -444,7 +440,52 @@ func TestFuncAIRS(t *testing.T) {
ret, err := uf.Call(&objects.Int{Value: 55})
assert.NoError(t, err)
assert.Equal(t, &objects.String{Value: "55"}, ret)
ret, err = uf.Call()
_, err = uf.Call()
assert.Equal(t, objects.ErrWrongNumArguments, err)
}
func TestFuncAIRIs(t *testing.T) {
uf := stdlib.FuncAIRIs(func(a int) []int { return []int{a, a} })
ret, err := uf.Call(&objects.Int{Value: 55})
assert.NoError(t, err)
assert.Equal(t, array(&objects.Int{Value: 55}, &objects.Int{Value: 55}), ret)
_, err = uf.Call()
assert.Equal(t, objects.ErrWrongNumArguments, err)
}
func TestFuncAI64R(t *testing.T) {
uf := stdlib.FuncAIR(func(a int) {})
ret, err := uf.Call(&objects.Int{Value: 55})
assert.NoError(t, err)
assert.Equal(t, objects.UndefinedValue, ret)
_, err = uf.Call()
assert.Equal(t, objects.ErrWrongNumArguments, err)
}
func TestFuncARI64(t *testing.T) {
uf := stdlib.FuncARI64(func() int64 { return 55 })
ret, err := uf.Call()
assert.NoError(t, err)
assert.Equal(t, &objects.Int{Value: 55}, ret)
_, err = uf.Call(&objects.Int{Value: 55})
assert.Equal(t, objects.ErrWrongNumArguments, err)
}
func TestFuncASsSRS(t *testing.T) {
uf := stdlib.FuncASsSRS(func(a []string, b string) string { return strings.Join(a, b) })
ret, err := uf.Call(array(&objects.String{Value: "abc"}, &objects.String{Value: "def"}), &objects.String{Value: "-"})
assert.NoError(t, err)
assert.Equal(t, &objects.String{Value: "abc-def"}, ret)
_, err = uf.Call()
assert.Equal(t, objects.ErrWrongNumArguments, err)
}
func TestFuncAI64RI64(t *testing.T) {
uf := stdlib.FuncAI64RI64(func(a int64) int64 { return a * 2 })
ret, err := uf.Call(&objects.Int{Value: 55})
assert.NoError(t, err)
assert.Equal(t, &objects.Int{Value: 110}, ret)
_, err = uf.Call()
assert.Equal(t, objects.ErrWrongNumArguments, err)
}

87
compiler/stdlib/rand.go Normal file
View file

@ -0,0 +1,87 @@
package stdlib
import (
"math/rand"
"github.com/d5/tengo/objects"
)
var randModule = map[string]objects.Object{
"int": FuncARI64(rand.Int63),
"float": FuncARF(rand.Float64),
"intn": FuncAI64RI64(rand.Int63n),
"exp_float": FuncARF(rand.ExpFloat64),
"norm_float": FuncARF(rand.NormFloat64),
"perm": FuncAIRIs(rand.Perm),
"seed": FuncAI64R(rand.Seed),
"read": &objects.UserFunction{
Value: func(args ...objects.Object) (ret objects.Object, err error) {
if len(args) != 1 {
return nil, objects.ErrWrongNumArguments
}
y1, ok := args[0].(*objects.Bytes)
if !ok {
return nil, objects.ErrInvalidTypeConversion
}
res, err := rand.Read(y1.Value)
if err != nil {
ret = wrapError(err)
return
}
return &objects.Int{Value: int64(res)}, nil
},
},
"rand": &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
}
src := rand.NewSource(i1)
return randRand(rand.New(src)), nil
},
},
}
func randRand(r *rand.Rand) *objects.ImmutableMap {
return &objects.ImmutableMap{
Value: map[string]objects.Object{
"int": FuncARI64(r.Int63),
"float": FuncARF(r.Float64),
"intn": FuncAI64RI64(r.Int63n),
"exp_float": FuncARF(r.ExpFloat64),
"norm_float": FuncARF(r.NormFloat64),
"perm": FuncAIRIs(r.Perm),
"seed": FuncAI64R(r.Seed),
"read": &objects.UserFunction{
Value: func(args ...objects.Object) (ret objects.Object, err error) {
if len(args) != 1 {
return nil, objects.ErrWrongNumArguments
}
y1, ok := args[0].(*objects.Bytes)
if !ok {
return nil, objects.ErrInvalidTypeConversion
}
res, err := r.Read(y1.Value)
if err != nil {
ret = wrapError(err)
return
}
return &objects.Int{Value: int64(res)}, nil
},
},
},
}
}

View file

@ -0,0 +1,45 @@
package stdlib_test
import (
"math/rand"
"testing"
"github.com/d5/tengo/assert"
"github.com/d5/tengo/objects"
)
func TestRand(t *testing.T) {
var seed int64 = 1234
r := rand.New(rand.NewSource(seed))
module(t, "rand").call("seed", seed).expect(objects.UndefinedValue)
module(t, "rand").call("int").expect(r.Int63())
module(t, "rand").call("float").expect(r.Float64())
module(t, "rand").call("intn", 111).expect(r.Int63n(111))
module(t, "rand").call("exp_float").expect(r.ExpFloat64())
module(t, "rand").call("norm_float").expect(r.NormFloat64())
module(t, "rand").call("perm", 10).expect(r.Perm(10))
buf1 := make([]byte, 10)
buf2 := &objects.Bytes{Value: make([]byte, 10)}
n, _ := r.Read(buf1)
module(t, "rand").call("read", buf2).expect(n)
assert.Equal(t, buf1, buf2.Value)
seed = 9191
r = rand.New(rand.NewSource(seed))
randObj := module(t, "rand").call("rand", seed)
randObj.call("seed", seed).expect(objects.UndefinedValue)
randObj.call("int").expect(r.Int63())
randObj.call("float").expect(r.Float64())
randObj.call("intn", 111).expect(r.Int63n(111))
randObj.call("exp_float").expect(r.ExpFloat64())
randObj.call("norm_float").expect(r.NormFloat64())
randObj.call("perm", 10).expect(r.Perm(10))
buf1 = make([]byte, 12)
buf2 = &objects.Bytes{Value: make([]byte, 12)}
n, _ = r.Read(buf1)
randObj.call("read", buf2).expect(n)
assert.Equal(t, buf1, buf2.Value)
}

View file

@ -8,4 +8,5 @@ var Modules = map[string]*objects.ImmutableMap{
"os": {Value: osModule},
"text": {Value: textModule},
"times": {Value: timesModule},
"rand": {Value: randModule},
}

View file

@ -122,6 +122,13 @@ func object(v interface{}) objects.Object {
return &objects.ImmutableArray{Value: objs}
case time.Time:
return &objects.Time{Value: v}
case []int:
var objs []objects.Object
for _, e := range v {
objs = append(objs, &objects.Int{Value: int64(e)})
}
return &objects.Array{Value: objs}
}
panic(fmt.Errorf("unknown type: %T", v))

28
docs/stdlib-rand.md Normal file
View file

@ -0,0 +1,28 @@
# Module - "rand"
```golang
rand := import("rand")
```
## Functions
- `seed(seed int)`: uses the provided seed value to initialize the default Source to a deterministic state.
- `exp_float() => float`: returns an exponentially distributed float64 in the range (0, +math.MaxFloat64] with an exponential distribution whose rate parameter (lambda) is 1 and whose mean is 1/lambda (1) from the default Source.
- `float() => float`: returns, as a float64, a pseudo-random number in [0.0,1.0) from the default Source.
- `int() => int`: returns a non-negative pseudo-random 63-bit integer as an int64 from the default Source.
- `intn(n int) => int`: returns, as an int64, a non-negative pseudo-random number in [0,n) from the default Source. It panics if n <= 0.
- `norm_float) => float`: returns a normally distributed float64 in the range [-math.MaxFloat64, +math.MaxFloat64] with standard normal distribution (mean = 0, stddev = 1) from the default Source.
- `perm(n int) => [int]`: returns, as a slice of n ints, a pseudo-random permutation of the integers [0,n) from the default Source.
- `read(p bytes) => int/error`: generates len(p) random bytes from the default Source and writes them into p. It always returns len(p) and a nil error.
- `rand(src_seed int) => Rand`: returns a new Rand that uses random values from src to generate other random values.
## Rand
- `seed(seed int)`: uses the provided seed value to initialize the default Source to a deterministic state.
- `exp_float() => float`: returns an exponentially distributed float64 in the range (0, +math.MaxFloat64] with an exponential distribution whose rate parameter (lambda) is 1 and whose mean is 1/lambda (1) from the default Source.
- `float() => float`: returns, as a float64, a pseudo-random number in [0.0,1.0) from the default Source.
- `int() => int`: returns a non-negative pseudo-random 63-bit integer as an int64 from the default Source.
- `intn(n int) => int`: returns, as an int64, a non-negative pseudo-random number in [0,n) from the default Source. It panics if n <= 0.
- `norm_float) => float`: returns a normally distributed float64 in the range [-math.MaxFloat64, +math.MaxFloat64] with standard normal distribution (mean = 0, stddev = 1) from the default Source.
- `perm(n int) => [int]`: returns, as a slice of n ints, a pseudo-random permutation of the integers [0,n) from the default Source.
- `read(p bytes) => int/error`: generates len(p) random bytes from the default Source and writes them into p. It always returns len(p) and a nil error.

View file

@ -3,4 +3,5 @@
- [os](https://github.com/d5/tengo/blob/master/docs/stdlib-os.md): platform-independent interface to operating system functionality.
- [text](https://github.com/d5/tengo/blob/master/docs/stdlib-text.md): regular expressions, string conversion, and manipulation
- [math](https://github.com/d5/tengo/blob/master/docs/stdlib-math.md): mathematical constants and functions
- [times](https://github.com/d5/tengo/blob/master/docs/stdlib-times.md): time-related functions
- [times](https://github.com/d5/tengo/blob/master/docs/stdlib-times.md): time-related functions
- [rand](https://github.com/d5/tengo/blob/master/docs/stdlib-rand.md): random functions