mirror of
https://github.com/go-sylixos/elvish.git
synced 2024-12-05 03:17:50 +08:00
eval: Convert return values in ReflectBuiltinFn.
This commit is contained in:
parent
098ca254f7
commit
ff71246139
|
@ -3,7 +3,6 @@ package eval
|
|||
import (
|
||||
"math"
|
||||
"math/rand"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// Numerical operations.
|
||||
|
@ -22,11 +21,11 @@ func init() {
|
|||
"+": plus,
|
||||
"-": minus,
|
||||
"*": times,
|
||||
"^": pow,
|
||||
"%": mod,
|
||||
"^": math.Pow,
|
||||
"%": func(a, b int) int { return a % b },
|
||||
|
||||
// Random
|
||||
"rand": randFn,
|
||||
"rand": rand.Float64,
|
||||
"randint": randint,
|
||||
})
|
||||
addToBuiltinFns([]*BuiltinFn{
|
||||
|
@ -34,31 +33,31 @@ func init() {
|
|||
})
|
||||
}
|
||||
|
||||
func plus(nums ...float64) string {
|
||||
func plus(nums ...float64) float64 {
|
||||
sum := 0.0
|
||||
for _, f := range nums {
|
||||
sum += f
|
||||
}
|
||||
return floatToString(sum)
|
||||
return sum
|
||||
}
|
||||
|
||||
func minus(sum float64, nums ...float64) string {
|
||||
func minus(sum float64, nums ...float64) float64 {
|
||||
if len(nums) == 0 {
|
||||
// Unary -
|
||||
return floatToString(-sum)
|
||||
return -sum
|
||||
}
|
||||
for _, f := range nums {
|
||||
sum -= f
|
||||
}
|
||||
return floatToString(sum)
|
||||
return sum
|
||||
}
|
||||
|
||||
func times(nums ...float64) string {
|
||||
func times(nums ...float64) float64 {
|
||||
prod := 1.0
|
||||
for _, f := range nums {
|
||||
prod *= f
|
||||
}
|
||||
return floatToString(prod)
|
||||
return prod
|
||||
}
|
||||
|
||||
func slash(ec *Frame, args []interface{}, opts map[string]interface{}) {
|
||||
|
@ -87,21 +86,9 @@ func divide(ec *Frame, args []interface{}, opts map[string]interface{}) {
|
|||
out <- floatToString(prod)
|
||||
}
|
||||
|
||||
func pow(b, p float64) string {
|
||||
return floatToString(math.Pow(b, p))
|
||||
}
|
||||
|
||||
func mod(a, b int) string {
|
||||
return strconv.Itoa(a % b)
|
||||
}
|
||||
|
||||
func randFn() string {
|
||||
return floatToString(rand.Float64())
|
||||
}
|
||||
|
||||
func randint(low, high int) (string, error) {
|
||||
func randint(low, high int) (int, error) {
|
||||
if low >= high {
|
||||
return "", ErrArgs
|
||||
return 0, ErrArgs
|
||||
}
|
||||
return strconv.Itoa(low + rand.Intn(high-low)), nil
|
||||
return low + rand.Intn(high-low), nil
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"unsafe"
|
||||
|
||||
"github.com/elves/elvish/eval/types"
|
||||
|
@ -33,7 +34,8 @@ func addToReflectBuiltinFns(moreFns map[string]interface{}) {
|
|||
// Return values go to the channel part of the stdout port. However, if the last
|
||||
// return value has type error and is not nil, it is turned into an exception
|
||||
// and no ouputting happens. If the last return value is a nil error, it is
|
||||
// ignored.
|
||||
// ignored. Return values of type int or float64 are converted to strings with
|
||||
// strconv.Itoa and strconv.FormatFloat(f, 'g', -1, 64) respectively.
|
||||
type ReflectBuiltinFn struct {
|
||||
name string
|
||||
impl interface{}
|
||||
|
@ -157,7 +159,7 @@ func (b *ReflectBuiltinFn) Call(f *Frame, args []interface{}, opts map[string]in
|
|||
}
|
||||
|
||||
for _, out := range outs {
|
||||
f.OutputChan() <- out.Interface()
|
||||
f.OutputChan() <- convertRet(out.Interface())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -188,3 +190,15 @@ func convertArg(arg interface{}, typ reflect.Type) (interface{}, error) {
|
|||
types.Kind(reflect.Zero(typ).Interface()), types.Kind(arg))
|
||||
}
|
||||
}
|
||||
|
||||
// convertRet converts the return value.
|
||||
func convertRet(ret interface{}) interface{} {
|
||||
switch ret := ret.(type) {
|
||||
case int:
|
||||
return strconv.Itoa(ret)
|
||||
case float64:
|
||||
return strconv.FormatFloat(ret, 'g', -1, 64)
|
||||
default:
|
||||
return ret
|
||||
}
|
||||
}
|
||||
|
|
|
@ -95,6 +95,18 @@ func TestReflectBuiltinFnCall(t *testing.T) {
|
|||
t.Errorf("Return value is not outputted")
|
||||
}
|
||||
|
||||
// Conversion of return values.
|
||||
f = NewReflectBuiltinFn("f", func() int { return 314 })
|
||||
callGood(outFrame, nil, theOptions)
|
||||
select {
|
||||
case ret := <-ch:
|
||||
if ret != "314" {
|
||||
t.Errorf("Return value is not converted to string")
|
||||
}
|
||||
default:
|
||||
t.Errorf("Return value is not outputted")
|
||||
}
|
||||
|
||||
// Passing of error return value.
|
||||
theError := errors.New("the error")
|
||||
f = NewReflectBuiltinFn("f", func() (string, error) {
|
||||
|
|
Loading…
Reference in New Issue
Block a user