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 "" } func (val ListValue) String() string { res := "[" sep := "" for _, elt := range val.List { 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) } /* Helpers to easily convert Muesli value lists to "normal" Go values. * The returned array are the remaining unparsed arguments. */ func ParseArgs(args []Value, to...interface{}) ([]Value, error) { if len(to) > len(args) { return nil, NewErrorValuef("Too few arguments, expected %d, got %d", len(to), len(args)) } i:= 0 for ; i < len(to) ; i ++ { fromElt := args[i] toElt := to[i] if fromElt == nil { return nil, NewErrorValuef("Nil value in argument %d", i) } err := fromElt.Convert(toElt) if err != nil { return nil, err } } rest := args[i:len(args)] return rest, nil } /* 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)} }