// Copyright (c) 2024-2026 Celestino Amoroso (celestino.amoroso@gmail.com). // All rights reserved. // dict-type.go package dict import ( "fmt" "reflect" "strings" "git.portale-stac.it/go-pkg/expr/kern" ) const DictTypeName = "dict" type DictType map[any]any func IsDict(v any) (ok bool) { _, ok = v.(*DictType) return ok } func MakeDict() (dict *DictType) { d := make(DictType) dict = &d return } func NewDict(dictAny map[any]any) (dict *DictType) { var d DictType if dictAny != nil { d = make(DictType, len(dictAny)) for i, item := range dictAny { d[i] = item } } else { d = make(DictType) } dict = &d return } func newDict(dictAny map[any]kern.Term) (dict *DictType) { // TODO Change with a call to NewDict() var d DictType if dictAny != nil { d = make(DictType, len(dictAny)) for i, item := range dictAny { d[i] = item } } else { d = make(DictType) } dict = &d return } func (dict *DictType) toMultiLine(sb *strings.Builder, opt kern.FmtOpt) { indent := kern.GetFormatIndent(opt) flags := kern.GetFormatFlags(opt) //sb.WriteString(strings.Repeat(" ", indent)) sb.WriteByte('{') if len(*dict) > 0 { innerOpt := kern.MakeFormatOptions(flags, indent+1) nest := strings.Repeat(" ", indent+1) sb.WriteByte('\n') first := true for name, value := range *dict { if first { first = false } else { sb.WriteByte(',') sb.WriteByte('\n') } sb.WriteString(nest) if key, ok := name.(string); ok { sb.WriteByte('"') sb.WriteString(key) sb.WriteByte('"') } else { fmt.Fprintf(sb, "%v", name) } sb.WriteString(": ") if f, ok := value.(kern.Formatter); ok { sb.WriteString(f.ToString(innerOpt)) } else if _, ok = value.(kern.Functor); ok { sb.WriteString("func(){}") } else { fmt.Fprintf(sb, "%v", value) } } sb.WriteByte('\n') sb.WriteString(strings.Repeat(" ", indent)) } sb.WriteString("}") } func (dict *DictType) ToString(opt kern.FmtOpt) string { var sb strings.Builder flags := kern.GetFormatFlags(opt) if flags&kern.MultiLine != 0 { dict.toMultiLine(&sb, opt) } else { sb.WriteByte('{') first := true for key, value := range *dict { if first { first = false } else { sb.WriteString(", ") } if s, ok := key.(string); ok { sb.WriteByte('"') sb.WriteString(s) sb.WriteByte('"') } else { fmt.Fprintf(&sb, "%v", key) } sb.WriteString(": ") if formatter, ok := value.(kern.Formatter); ok { sb.WriteString(formatter.ToString(opt)) } else if t, ok := value.(kern.Term); ok { sb.WriteString(t.String()) } else { fmt.Fprintf(&sb, "%#v", value) } } sb.WriteByte('}') } return sb.String() } func (dict *DictType) String() string { return dict.ToString(0) } func (dict *DictType) TypeName() string { return DictTypeName } func (dict *DictType) HasKey(target any) (ok bool) { for key := range *dict { if ok = reflect.DeepEqual(key, target); ok { break } } return } func (dict *DictType) SetItem(key any, value any) { (*dict)[key] = value } func (dict *DictType) GetItem(key any) (value any, exists bool) { value, exists = (*dict)[key] return } func (dict *DictType) FindKey(item any) (key any, exists bool) { for k, v := range *dict { if kern.Equal(v, item) { key = k exists = true break } } return } func (dict *DictType) Clone() kern.Cloner { c := newDict(nil) for k, v := range *dict { (*c)[k] = kern.Clone(v) } return c } func (dict *DictType) Merge(second *DictType) { if second != nil { for k, v := range *second { (*dict)[k] = v } } } func (dict *DictType) EqualTo(other kern.Equaler) (answer bool) { if dict2, ok := other.(*DictType); ok { answer = dict.Equals(*dict2) } return } func (dict *DictType) Equals(dict2 DictType) (answer bool) { if dict2 != nil && len(*dict) == len(dict2) { answer = true for key, value1 := range *dict { if value2, exists := dict2.GetItem(key); exists { if !kern.Equal(value1, value2) { answer = false break } } else { answer = false break } } } return } //////////////// // type DictFormat interface { // ToDict() *DictType // }