123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542 |
- package muesli
- import "fmt"
- /* Run time values */
- type Value interface {
- String() string
- Type() TypeValue
- // Convert the value to a normal go value which must be passed
- // in as a pointer to which the value mmust be set,
- // or return an error if the concversion is not possible.
- Convert(to interface{}) error
- }
- type IntValue int64
- type FloatValue float64
- type StringValue string
- type BoolValue bool
- type WordValue string
- type TypeValue string
- type ErrorValue struct {
- error
- }
- type EmptyValue struct {
- }
- type ListValue struct {
- List []Value
- }
- type MapValue struct {
- Map map[Value]Value
- }
- // Values is simply a shorthand alias for []Value
- type Values = []Value
- const (
- TrueValue = BoolValue(true)
- FalseValue = BoolValue(false)
- IntTypeValue = TypeValue("Int")
- FloatTypeValue = TypeValue("Float")
- StringTypeValue = TypeValue("String")
- BoolTypeValue = TypeValue("Bool")
- WordTypeValue = TypeValue("Word")
- ErrorTypeValue = TypeValue("Error")
- TypeTypeValue = TypeValue("Type")
- EmptyTypeValue = TypeValue("Empty")
- ListTypeValue = TypeValue("List")
- MapTypeValue = TypeValue("Map")
- AnyTypeValue = TypeValue("Any")
- ZeroTypeValue = TypeValue("")
- )
- var NilValue = Value(nil)
- func (val IntValue) String() string {
- return fmt.Sprintf("%d", int64(val))
- }
- func (val FloatValue) String() string {
- return fmt.Sprintf("%f", float64(val))
- }
- func (val BoolValue) String() string {
- if bool(val) {
- return "true"
- } else {
- return "false"
- }
- }
- func (val StringValue) String() string {
- return string(val)
- }
- func (val WordValue) String() string {
- return string(val)
- }
- func (val TypeValue) String() string {
- return string(val)
- }
- func (val ErrorValue) String() string {
- return fmt.Sprintf("%s", val.Error())
- }
- func (val EmptyValue) String() string {
- return "<empty>"
- }
- func (val ListValue) String() string {
- res := "["
- sep := ""
- for _, elt := range val.List {
- if elt == nil {
- res = res + sep + "nil"
- } else {
- res = res + sep + elt.String()
- }
- sep = ", "
- }
- res += "]"
- return res
- }
- func (val MapValue) String() string {
- res := "{"
- sep := ""
- for k, v := range val.Map {
- res = res + sep + k.String() + "=>" + v.String()
- sep = ", "
- }
- res += "}"
- return res
- }
- func (v IntValue) Type() TypeValue { return IntTypeValue }
- func (v FloatValue) Type() TypeValue { return FloatTypeValue }
- func (v StringValue) Type() TypeValue { return StringTypeValue }
- func (v BoolValue) Type() TypeValue { return BoolTypeValue }
- func (v WordValue) Type() TypeValue { return WordTypeValue }
- func (v TypeValue) Type() TypeValue { return TypeTypeValue }
- func (v ErrorValue) Type() TypeValue { return ErrorTypeValue }
- func (v EmptyValue) Type() TypeValue { return EmptyTypeValue }
- func (v ListValue) Type() TypeValue { return ListTypeValue }
- func (v MapValue) Type() TypeValue { return MapTypeValue }
- func NewErrorValuef(format string, args ...interface{}) ErrorValue {
- err := fmt.Errorf(format, args...)
- return ErrorValue{err}
- }
- func NewListValue(elements ...Value) * ListValue {
- return &ListValue{elements}
- }
- func (list *ListValue) Append(elements ...Value) {
- list.List = append(list.List, elements...)
- }
- func (list *ListValue) AppendList(toAppend ListValue) {
- list.List = append(list.List, toAppend.List...)
- }
- func (list ListValue) Length() int {
- return len(list.List)
- }
- func (list *ListValue) Fetch(i int) Value {
- if i >= len(list.List) {
- return NilValue
- }
- return list.List[i]
- }
- func (list *ListValue) Place(i int, v Value) Value {
- if i >= len(list.List) {
- return NilValue
- }
- list.List[i] = v
- return list.List[i]
- }
- func (list *ListValue) First() Value {
- return list.Fetch(0)
- }
- func (list *ListValue) Last() Value {
- return list.Fetch(list.Length()-1)
- }
- func EmptyListValue() ListValue {
- return ListValue{make([]Value, 0)}
- }
- func EmptyValueArray() []Value {
- return make([]Value, 0)
- }
- func NewValueArray(elements ...Value) []Value {
- return elements
- }
- func NewMapValue(elements map[Value]Value) * MapValue {
- return &MapValue{elements}
- }
- func (m *MapValue) Fetch(key Value) Value {
- var res Value
- var ok bool
- if res, ok = m.Map[key] ; !ok {
- return NilValue
- }
- return res
- }
- func (m *MapValue) Place(key Value, value Value) Value {
- m.Map[key] = value
- return m.Map[key]
- }
- func (from IntValue) Convert(to interface{}) error {
- switch toPtr := to.(type) {
- case *string:
- (*toPtr) = from.String()
- case *int8:
- (*toPtr) = int8(from)
- case *int16:
- (*toPtr) = int16(from)
- case *int32:
- (*toPtr) = int32(from)
- case *int64:
- (*toPtr) = int64(from)
- case *int:
- (*toPtr) = int(from)
- case *bool:
- (*toPtr) = (from != 0)
- case *float32:
- (*toPtr) = float32(from)
- case *float64:
- (*toPtr) = float64(from)
- case *IntValue:
- (*toPtr) = from
- case *Value:
- (*toPtr) = from
- default:
- return NewErrorValuef("Cannot convert IntValue value %v to %v", from, to)
- }
- return nil
- }
- func (from FloatValue) Convert(to interface{}) error {
- switch toPtr := to.(type) {
- case *string:
- (*toPtr) = from.String()
- case *int8:
- (*toPtr) = int8(from)
- case *int16:
- (*toPtr) = int16(from)
- case *int32:
- (*toPtr) = int32(from)
- case *int64:
- (*toPtr) = int64(from)
- case *int:
- (*toPtr) = int(from)
- case *bool:
- (*toPtr) = (from != 0)
- case *float32:
- (*toPtr) = float32(from)
- case *float64:
- (*toPtr) = float64(from)
- case *FloatValue:
- (*toPtr) = from
- case *Value:
- (*toPtr) = from
- default:
- return NewErrorValuef("Cannot convert FloatValue value %v to %v", from, to)
- }
- return nil
- }
-
- func (from StringValue) Convert(to interface{}) error {
- switch toPtr := to.(type) {
- case *string:
- (*toPtr) = from.String()
- case *StringValue:
- (*toPtr) = from
- case *Value:
- (*toPtr) = from
- default:
- return NewErrorValuef("Cannot convert StringValue %v to %v", from, to)
- }
- return nil
- }
- func (from WordValue) Convert(to interface{}) error {
- switch toPtr := to.(type) {
- case *string:
- (*toPtr) = from.String()
- case *WordValue:
- (*toPtr) = from
- case *Value:
- (*toPtr) = from
- default:
- return NewErrorValuef("Cannot convert WordValue %v to %v", from, to)
- }
- return nil
- }
- func (from TypeValue) Convert(to interface{}) error {
- switch toPtr := to.(type) {
- case *string:
- (*toPtr) = from.String()
- case *TypeValue:
- (*toPtr) = from
- case *Value:
- (*toPtr) = from
- default:
- return NewErrorValuef("Cannot convert value %v to %v", from, to)
- }
- return nil
- }
- func (from BoolValue) Convert(to interface{}) error {
- switch toPtr := to.(type) {
- case *bool:
- (*toPtr) = bool(from)
- case *BoolValue:
- (*toPtr) = from
- case *Value:
- (*toPtr) = from
- default:
- return NewErrorValuef("Cannot convert value %v to %v", from, to)
- }
- return nil
- }
- func (from ErrorValue) Convert(to interface{}) error {
- switch toPtr := to.(type) {
- case *string:
- (*toPtr) = from.String()
- case *error:
- (*toPtr) = from.error
- case *ErrorValue:
- (*toPtr) = from
- case *Value:
- (*toPtr) = from
- default:
- return NewErrorValuef("Cannot convert value %v to %v", from, to)
- }
- return nil
- }
- func (from EmptyValue) Convert(to interface{}) error {
- return NewErrorValuef("Cannot convert the empty value %v to %v", from, to)
- }
- func (from * ListValue) Convert(to interface{}) error {
- switch toPtr := to.(type) {
- case *[]Value:
- (*toPtr) = from.List
- case **ListValue:
- (*toPtr) = from
- case *Value:
- (*toPtr) = from
- default:
- return NewErrorValuef("Cannot convert value %v to %v", from, to)
- }
- return nil
- }
- func (from * MapValue) Convert(to interface{}) error {
- switch toPtr := to.(type) {
- case *map[Value]Value:
- (*toPtr) = from.Map
- case **MapValue:
- (*toPtr) = from
- case *Value:
- (*toPtr) = from
- default:
- return NewErrorValuef("Cannot convert value %v to %v", from, to)
- }
- return nil
- }
- /* Helpers to easily convert Muesli values to "normal" Go values. */
- func From(from Value, to interface{}) error {
- return from.Convert(to)
- }
- // ParseOptArgs ia helper to easily convert Muesli value lists to "normal"
- // Go values. args is the input, required is the amount of required aruments,
- // and to are pointers to where to store the data. The args are converted by
- // calling the Convert() method on them.
- // The returned array contains the remaining unparsed arguments.
- func ParseOptArgs(args []Value, required int, to...interface{}) ([]Value, error) {
- if required > len(args) {
- return nil, NewErrorValuef("Too few arguments, expected %d, got %d", required, len(args))
- }
- stop := len(args)
- if len(to) < stop {
- stop = len(to)
- }
- i:= 0
- for ; i < stop ; i ++ {
- fromElt := args[i]
- toElt := to[i]
- if fromElt == nil {
- return nil, NewErrorValuef("Nil pointer to result %d", i)
- }
- err := fromElt.Convert(toElt)
- if err != nil {
- return nil, err
- }
- }
- rest := args[i:len(args)]
- return rest, nil
- }
- // ParseArgs is helper to easily convert Muesli value lists to "normal"
- // Go values. It is the same as ParseOptArgs(args, len(to, to...)
- func ParseArgs(args []Value, to...interface{}) ([]Value, error) {
- return ParseOptArgs(args, len(to), to...)
- }
- /* Helpers to easily convert Muesli value lists to "normal" Go values in slices. */
- func ParseArgsToIntSlice(args []Value) ([]int, error) {
- res := []int{}
- for _, arg := range args{
- value := int(0)
- err := arg.Convert(&value)
- if err != nil {
- return res, err
- }
- res = append(res, value)
- }
-
- return res, nil
- }
- /* Helpers to easily convert Muesli value lists to "normal" Go values in slices. */
- func ParseArgsToFloat64Slice(args []Value) ([]float64, error) {
- res := []float64{}
- for _, arg := range args{
- value := float64(0.0)
- err := arg.Convert(&value)
- if err != nil {
- return res, err
- }
- res = append(res, value)
- }
-
- return res, nil
- }
- /* Helpers to easily convert Muesli values from "normal" Go values. */
- func To(from interface{}) Value {
- switch val := from.(type) {
- case string:
- return StringValue(val)
- case int8:
- return IntValue(val)
- case int16:
- return IntValue(val)
- case int32:
- return IntValue(val)
- case int64:
- return IntValue(val)
- case int:
- return IntValue(val)
- case bool:
- return BoolValue(val)
- case float32:
- return FloatValue(val)
- case float64:
- return FloatValue(val)
- case error:
- return ErrorValue{val}
- case Value:
- return val
- default:
- return NewErrorValuef("Cannot convert value %v", from)
- }
- }
- func ListTo(froms ...interface{}) []Value {
- list := make([]Value, 0)
- for _, from := range froms {
- val := To(from)
- list = append(list, val)
- }
- return list
- }
- func ListFrom(froms []Value, tos ...interface{}) error {
- for i, from := range froms {
- if i >= len(tos) {
- break
- }
- err := From(from, tos[i])
- if err != nil {
- return err
- }
- }
- return nil
- }
- func ListFromList(froms []Value) []interface{} {
- res := make([]interface{}, len(froms))
- for i, from := range froms {
- res[i] = from
- }
- return res
- }
- func Return(args ... Value) []Value {
- return args
- }
- func ReturnEmpty() []Value {
- return []Value{EmptyValue{}}
- }
- func ReturnError(err error) []Value {
- return []Value{ErrorValue{err}}
- }
- func Ok(args ... Value) []Value {
- return args
- }
- func Fail(err error) []Value {
- return []Value{ErrorValue{err}}
- }
- func None() []Value {
- return []Value{EmptyValue{}}
- }
- func BoolOk(b bool) []Value{
- return []Value{BoolValue(b)}
- }
- func IntOk(i int) []Value{
- return []Value{IntValue(i)}
- }
- func FloatOk(f float64) []Value{
- return []Value{FloatValue(f)}
- }
|