mirror of
https://github.com/go-sylixos/elvish.git
synced 2024-12-01 00:33:05 +08:00
Fixup for #1760.
- Use standard error types. - Support float64 that stores an integer. - Don't incur unnecessary overhead for int arguments.
This commit is contained in:
parent
183927cffc
commit
27495be1b9
|
@ -2,10 +2,14 @@ package eval
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"math/big"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"src.elv.sh/pkg/eval/errs"
|
||||
"src.elv.sh/pkg/eval/vals"
|
||||
"src.elv.sh/pkg/wcwidth"
|
||||
)
|
||||
|
@ -45,31 +49,39 @@ func toString(fm *Frame, args ...any) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// ErrBadBase is thrown by the "base" builtin if the base is smaller than 2 or
|
||||
// greater than 36.
|
||||
var ErrBadBase = errors.New("bad base")
|
||||
|
||||
// ErrInvalidInput is thrown by the "base" builtin if the input num is invalid
|
||||
var ErrInvalidInput = errors.New("invalid input")
|
||||
|
||||
func base(fm *Frame, b int, nums ...vals.Num) error {
|
||||
if b < 2 || b > 36 {
|
||||
return ErrBadBase
|
||||
return errs.OutOfRange{What: "base",
|
||||
ValidLow: "2", ValidHigh: "36", Actual: strconv.Itoa(b)}
|
||||
}
|
||||
// Don't output anything yet in case some arguments are invalid.
|
||||
results := make([]string, len(nums))
|
||||
for i, num := range nums {
|
||||
switch num := num.(type) {
|
||||
case int:
|
||||
results[i] = strconv.FormatInt(int64(num), b)
|
||||
case *big.Int:
|
||||
results[i] = num.Text(b)
|
||||
case float64:
|
||||
if i64 := int64(num); float64(i64) == num {
|
||||
results[i] = strconv.FormatInt(i64, b)
|
||||
} else if num == math.Trunc(num) {
|
||||
var z big.Int
|
||||
z.SetString(fmt.Sprintf("%.0f", num), 10)
|
||||
results[i] = z.Text(b)
|
||||
} else {
|
||||
return errs.BadValue{What: "number",
|
||||
Valid: "integer", Actual: vals.ReprPlain(num)}
|
||||
}
|
||||
default:
|
||||
return errs.BadValue{What: "number",
|
||||
Valid: "integer", Actual: vals.ReprPlain(num)}
|
||||
}
|
||||
}
|
||||
|
||||
out := fm.ValueOutput()
|
||||
for _, num := range nums {
|
||||
bigInt := new(big.Int)
|
||||
switch num := num.(type) {
|
||||
case int:
|
||||
bigInt.SetInt64(int64(num))
|
||||
case *big.Int:
|
||||
bigInt.Set(num)
|
||||
default:
|
||||
return ErrInvalidInput
|
||||
}
|
||||
|
||||
err := out.Put(bigInt.Text(b))
|
||||
for _, s := range results {
|
||||
err := out.Put(s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -62,19 +62,29 @@ Exception: port does not support value output
|
|||
▶ 56bc75e2d63100000
|
||||
~> base 10 0x56bc75e2d63100000
|
||||
▶ 100000000000000000000
|
||||
// float64 storing an integer
|
||||
~> base 16 256.0
|
||||
▶ 100
|
||||
// float64 storing an integer that doesn't fit in int64
|
||||
~> base 16 100000000000000000000.0
|
||||
▶ 56bc75e2d63100000
|
||||
// typed number as arguments
|
||||
~> base (num 16) (num 256)
|
||||
▶ 100
|
||||
// bubbling output error
|
||||
// bad arguments
|
||||
~> base 16 1.2
|
||||
Exception: bad value: number must be integer, but is (num 1.2)
|
||||
[tty]:1:1-11: base 16 1.2
|
||||
~> base 8 1/8
|
||||
Exception: invalid input
|
||||
Exception: bad value: number must be integer, but is (num 1/8)
|
||||
[tty]:1:1-10: base 8 1/8
|
||||
~> base 1 1
|
||||
Exception: bad base
|
||||
Exception: out of range: base must be from 2 to 36, but is 1
|
||||
[tty]:1:1-8: base 1 1
|
||||
~> base 37 10
|
||||
Exception: bad base
|
||||
Exception: out of range: base must be from 2 to 36, but is 37
|
||||
[tty]:1:1-10: base 37 10
|
||||
// bubbling output error
|
||||
~> base 2 1 >&-
|
||||
Exception: port does not support value output
|
||||
[tty]:1:1-12: base 2 1 >&-
|
||||
|
|
Loading…
Reference in New Issue
Block a user