separate objects conversion functions

This commit is contained in:
Daniel Kang 2019-01-17 16:52:07 -08:00
parent cb5cbad3ad
commit 552e9c01c5
3 changed files with 174 additions and 56 deletions

View file

@ -1,22 +1,20 @@
package objects
import (
"strconv"
)
func builtinString(args ...Object) (Object, error) {
if len(args) != 1 {
return nil, ErrWrongNumArguments
}
switch arg := args[0].(type) {
case *String:
return arg, nil
case *Undefined:
return UndefinedValue, nil
default:
return &String{Value: arg.String()}, nil
if _, ok := args[0].(*String); ok {
return args[0], nil
}
v, ok := ToString(args[0])
if ok {
return &String{Value: v}, nil
}
return UndefinedValue, nil
}
func builtinInt(args ...Object) (Object, error) {
@ -24,23 +22,13 @@ func builtinInt(args ...Object) (Object, error) {
return nil, ErrWrongNumArguments
}
switch arg := args[0].(type) {
case *Int:
return arg, nil
case *Float:
return &Int{Value: int64(arg.Value)}, nil
case *Char:
return &Int{Value: int64(arg.Value)}, nil
case *Bool:
if arg.Value {
return &Int{Value: 1}, nil
}
return &Int{Value: 0}, nil
case *String:
n, err := strconv.ParseInt(arg.Value, 10, 64)
if err == nil {
return &Int{Value: n}, nil
}
if _, ok := args[0].(*Int); ok {
return args[0], nil
}
v, ok := ToInt64(args[0])
if ok {
return &Int{Value: v}, nil
}
return UndefinedValue, nil
@ -51,16 +39,13 @@ func builtinFloat(args ...Object) (Object, error) {
return nil, ErrWrongNumArguments
}
switch arg := args[0].(type) {
case *Float:
return arg, nil
case *Int:
return &Float{Value: float64(arg.Value)}, nil
case *String:
f, err := strconv.ParseFloat(arg.Value, 64)
if err == nil {
return &Float{Value: f}, nil
}
if _, ok := args[0].(*Float); ok {
return args[0], nil
}
v, ok := ToFloat64(args[0])
if ok {
return &Float{Value: v}, nil
}
return UndefinedValue, nil
@ -71,12 +56,16 @@ func builtinBool(args ...Object) (Object, error) {
return nil, ErrWrongNumArguments
}
switch arg := args[0].(type) {
case *Bool:
return arg, nil
default:
return &Bool{Value: !arg.IsFalsy()}, nil
if _, ok := args[0].(*Bool); ok {
return args[0], nil
}
v, ok := ToBool(args[0])
if ok {
return &Bool{Value: v}, nil
}
return UndefinedValue, nil
}
func builtinChar(args ...Object) (Object, error) {
@ -84,19 +73,13 @@ func builtinChar(args ...Object) (Object, error) {
return nil, ErrWrongNumArguments
}
switch arg := args[0].(type) {
case *Char:
return arg, nil
case *Int:
return &Char{Value: rune(arg.Value)}, nil
case *String:
rs := []rune(arg.Value)
switch len(rs) {
case 0:
return &Char{}, nil
case 1:
return &Char{Value: rs[0]}, nil
}
if _, ok := args[0].(*Char); ok {
return args[0], nil
}
v, ok := ToRune(args[0])
if ok {
return &Char{Value: v}, nil
}
return UndefinedValue, nil

132
objects/conversion.go Normal file
View file

@ -0,0 +1,132 @@
package objects
import (
"strconv"
)
// ToString will try to convert object o to string value.
func ToString(o Object) (v string, ok bool) {
if _, isUndefined := o.(*Undefined); isUndefined {
//ok = false
return
}
ok = true
if str, isStr := o.(*String); isStr {
v = str.Value
} else {
v = o.String()
}
return
}
// ToInt will try to convert object o to int value.
func ToInt(o Object) (v int, ok bool) {
switch o := o.(type) {
case *Int:
v = int(o.Value)
ok = true
case *Float:
v = int(o.Value)
ok = true
case *Char:
v = int(o.Value)
ok = true
case *Bool:
if o.Value {
v = 1
}
ok = true
case *String:
c, err := strconv.ParseInt(o.Value, 10, 64)
if err == nil {
v = int(c)
ok = true
}
}
//ok = false
return
}
// ToInt64 will try to convert object o to int64 value.
func ToInt64(o Object) (v int64, ok bool) {
switch o := o.(type) {
case *Int:
v = o.Value
ok = true
case *Float:
v = int64(o.Value)
ok = true
case *Char:
v = int64(o.Value)
ok = true
case *Bool:
if o.Value {
v = 1
}
ok = true
case *String:
c, err := strconv.ParseInt(o.Value, 10, 64)
if err == nil {
v = c
ok = true
}
}
//ok = false
return
}
// ToFloat64 will try to convert object o to float64 value.
func ToFloat64(o Object) (v float64, ok bool) {
switch o := o.(type) {
case *Int:
v = float64(o.Value)
ok = true
case *Float:
v = o.Value
ok = true
case *String:
c, err := strconv.ParseFloat(o.Value, 64)
if err == nil {
v = c
ok = true
}
}
//ok = false
return
}
// ToBool will try to convert object o to bool value.
func ToBool(o Object) (v bool, ok bool) {
ok = true
v = !o.IsFalsy()
return
}
// ToRune will try to convert object o to rune value.
func ToRune(o Object) (v rune, ok bool) {
switch o := o.(type) {
case *Int:
v = rune(o.Value)
ok = true
case *Char:
v = rune(o.Value)
ok = true
case *String:
rs := []rune(o.Value)
switch len(rs) {
case 1:
v = rs[0]
ok = true
}
}
//ok = false
return
}

View file

@ -7,3 +7,6 @@ var ErrInvalidOperator = errors.New("invalid operator")
// ErrWrongNumArguments represents a wrong number of arguments error.
var ErrWrongNumArguments = errors.New("wrong number of arguments")
// ErrInvalidTypeConversion represents an invalid type conversion error.
var ErrInvalidTypeConversion = errors.New("invalid type conversion")