mirror of
https://github.com/issadarkthing/gomu.git
synced 2025-04-26 13:49:21 +08:00
add type casting
This commit is contained in:
parent
9969c5eaf0
commit
b7d969be17
@ -20,9 +20,11 @@ type Anko struct {
|
||||
}
|
||||
|
||||
func NewAnko() Anko {
|
||||
return Anko{
|
||||
core.Import(env.NewEnv()),
|
||||
}
|
||||
|
||||
env := core.Import(env.NewEnv())
|
||||
importToX(env)
|
||||
|
||||
return Anko{env}
|
||||
}
|
||||
|
||||
// Define defines new symbol and value to the Anko env.
|
||||
|
171
anko/convert.go
Normal file
171
anko/convert.go
Normal file
@ -0,0 +1,171 @@
|
||||
package anko
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/mattn/anko/env"
|
||||
)
|
||||
|
||||
// importToX adds all the toX to the env given
|
||||
func importToX(e *env.Env) {
|
||||
|
||||
e.Define("to_bool", func(v interface{}) bool {
|
||||
rv := reflect.ValueOf(v)
|
||||
if !rv.IsValid() {
|
||||
return false
|
||||
}
|
||||
nt := reflect.TypeOf(true)
|
||||
if rv.Type().ConvertibleTo(nt) {
|
||||
return rv.Convert(nt).Bool()
|
||||
}
|
||||
if rv.Type().ConvertibleTo(reflect.TypeOf(1.0)) && rv.Convert(reflect.TypeOf(1.0)).Float() > 0.0 {
|
||||
return true
|
||||
}
|
||||
if rv.Kind() == reflect.String {
|
||||
s := strings.ToLower(v.(string))
|
||||
if s == "y" || s == "yes" {
|
||||
return true
|
||||
}
|
||||
b, err := strconv.ParseBool(s)
|
||||
if err == nil {
|
||||
return b
|
||||
}
|
||||
}
|
||||
return false
|
||||
})
|
||||
|
||||
e.Define("to_string", func(v interface{}) string {
|
||||
if b, ok := v.([]byte); ok {
|
||||
return string(b)
|
||||
}
|
||||
return fmt.Sprint(v)
|
||||
})
|
||||
|
||||
e.Define("to_int", func(v interface{}) int64 {
|
||||
rv := reflect.ValueOf(v)
|
||||
if !rv.IsValid() {
|
||||
return 0
|
||||
}
|
||||
nt := reflect.TypeOf(1)
|
||||
if rv.Type().ConvertibleTo(nt) {
|
||||
return rv.Convert(nt).Int()
|
||||
}
|
||||
if rv.Kind() == reflect.String {
|
||||
i, err := strconv.ParseInt(v.(string), 10, 64)
|
||||
if err == nil {
|
||||
return i
|
||||
}
|
||||
f, err := strconv.ParseFloat(v.(string), 64)
|
||||
if err == nil {
|
||||
return int64(f)
|
||||
}
|
||||
}
|
||||
if rv.Kind() == reflect.Bool {
|
||||
if v.(bool) {
|
||||
return 1
|
||||
}
|
||||
}
|
||||
return 0
|
||||
})
|
||||
|
||||
e.Define("to_float", func(v interface{}) float64 {
|
||||
rv := reflect.ValueOf(v)
|
||||
if !rv.IsValid() {
|
||||
return 0
|
||||
}
|
||||
nt := reflect.TypeOf(1.0)
|
||||
if rv.Type().ConvertibleTo(nt) {
|
||||
return rv.Convert(nt).Float()
|
||||
}
|
||||
if rv.Kind() == reflect.String {
|
||||
f, err := strconv.ParseFloat(v.(string), 64)
|
||||
if err == nil {
|
||||
return f
|
||||
}
|
||||
}
|
||||
if rv.Kind() == reflect.Bool {
|
||||
if v.(bool) {
|
||||
return 1.0
|
||||
}
|
||||
}
|
||||
return 0.0
|
||||
})
|
||||
|
||||
e.Define("to_char", func(s rune) string {
|
||||
return string(s)
|
||||
})
|
||||
|
||||
e.Define("to_rune", func(s string) rune {
|
||||
if len(s) == 0 {
|
||||
return 0
|
||||
}
|
||||
return []rune(s)[0]
|
||||
})
|
||||
|
||||
e.Define("to_bool_slice", func(v []interface{}) []bool {
|
||||
var result []bool
|
||||
toSlice(v, &result)
|
||||
return result
|
||||
})
|
||||
|
||||
e.Define("to_string_slice", func(v []interface{}) []string {
|
||||
var result []string
|
||||
toSlice(v, &result)
|
||||
return result
|
||||
})
|
||||
|
||||
e.Define("to_int_slice", func(v []interface{}) []int64 {
|
||||
var result []int64
|
||||
toSlice(v, &result)
|
||||
return result
|
||||
})
|
||||
|
||||
e.Define("to_float_slice", func(v []interface{}) []float64 {
|
||||
var result []float64
|
||||
toSlice(v, &result)
|
||||
return result
|
||||
})
|
||||
|
||||
e.Define("to_byte_slice", func(s string) []byte {
|
||||
return []byte(s)
|
||||
})
|
||||
|
||||
e.Define("to_runeSlice", func(s string) []rune {
|
||||
return []rune(s)
|
||||
})
|
||||
|
||||
e.Define("to_duration", func(v int64) time.Duration {
|
||||
return time.Duration(v)
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
// toSlice takes in a "generic" slice and converts and copies
|
||||
// it's elements into the typed slice pointed at by ptr.
|
||||
// Note that this is a costly operation.
|
||||
func toSlice(from []interface{}, ptr interface{}) {
|
||||
// Value of the pointer to the target
|
||||
obj := reflect.Indirect(reflect.ValueOf(ptr))
|
||||
// We can't just convert from interface{} to whatever the target is (diff memory layout),
|
||||
// so we need to create a New slice of the proper type and copy the values individually
|
||||
t := reflect.TypeOf(ptr).Elem()
|
||||
tt := t.Elem()
|
||||
slice := reflect.MakeSlice(t, len(from), len(from))
|
||||
// Copying the data, val is an addressable Pointer of the actual target type
|
||||
val := reflect.Indirect(reflect.New(tt))
|
||||
for i := 0; i < len(from); i++ {
|
||||
v := reflect.ValueOf(from[i])
|
||||
if v.IsValid() && v.Type().ConvertibleTo(tt) {
|
||||
val.Set(v.Convert(tt))
|
||||
} else {
|
||||
val.Set(reflect.Zero(tt))
|
||||
}
|
||||
slice.Index(i).Set(val)
|
||||
}
|
||||
// Ok now assign our slice to the target pointer
|
||||
obj.Set(slice)
|
||||
}
|
@ -65,7 +65,7 @@ module keybinds {
|
||||
module playlist {
|
||||
e = func() {
|
||||
val = 10 + 10
|
||||
debug_popup(val)
|
||||
debug_popup(to_string(val))
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user