add 'rand' module (#90)
This commit is contained in:
parent
9782d87c35
commit
2b517f376e
8 changed files with 344 additions and 54 deletions
|
@ -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 {
|
||||
|
|
|
@ -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
87
compiler/stdlib/rand.go
Normal 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
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
45
compiler/stdlib/rand_test.go
Normal file
45
compiler/stdlib/rand_test.go
Normal 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)
|
||||
}
|
|
@ -8,4 +8,5 @@ var Modules = map[string]*objects.ImmutableMap{
|
|||
"os": {Value: osModule},
|
||||
"text": {Value: textModule},
|
||||
"times": {Value: timesModule},
|
||||
"rand": {Value: randModule},
|
||||
}
|
||||
|
|
|
@ -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
28
docs/stdlib-rand.md
Normal 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.
|
|
@ -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
|
Loading…
Reference in a new issue