// Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com). // All rights reserved. // operand-dict.go package expr import ( "fmt" "reflect" "strings" ) type DictType map[any]any func newDict(dictAny map[any]*term) (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 (dict *DictType) toMultiLine(sb *strings.Builder, indent int) { sb.WriteString(strings.Repeat("\t", indent)) sb.WriteString("{\n") first := true for name, value := range *dict { if first { first = false } else { sb.WriteByte(',') sb.WriteByte('\n') } sb.WriteString(strings.Repeat("\t", indent+1)) if key, ok := name.(string); ok { sb.WriteString(string('"') + key + string('"')) } else { sb.WriteString(fmt.Sprintf("%v", name)) } sb.WriteString(": ") if f, ok := value.(Formatter); ok { sb.WriteString(f.ToString(MultiLine)) } else if _, ok = value.(Functor); ok { sb.WriteString("func(){}") } else { sb.WriteString(fmt.Sprintf("%v", value)) } } sb.WriteString(strings.Repeat("\t", indent)) sb.WriteString("\n}") } func (dict *DictType) ToString(opt FmtOpt) string { var sb strings.Builder if opt&MultiLine != 0 { dict.toMultiLine(&sb, 0) } else { sb.WriteByte('{') first := true for key, value := range *dict { if first { first = false } else { sb.WriteString(", ") } if s, ok := key.(string); ok { sb.WriteString(string('"') + s + string('"')) } else { sb.WriteString(fmt.Sprintf("%v", key)) } sb.WriteString(": ") if formatter, ok := value.(Formatter); ok { sb.WriteString(formatter.ToString(opt)) } else if t, ok := value.(*term); ok { sb.WriteString(t.String()) } else { sb.WriteString(fmt.Sprintf("%#v", value)) } } sb.WriteByte('}') } return sb.String() } func (dict *DictType) String() string { return dict.ToString(0) } func (dict *DictType) TypeName() string { return "dict" } func (dict *DictType) hasKey(target any) (ok bool) { for key := range *dict { if ok = reflect.DeepEqual(key, target); ok { break } } return } func (dict *DictType) clone() (c *DictType) { c = newDict(nil) for k, v := range *dict { (*c)[k] = v } return } func (dict *DictType) merge(second *DictType) { if second != nil { for k, v := range *second { (*dict)[k] = v } } } // -------- dict term func newDictTerm(args map[any]*term) *term { return &term{ tk: *NewValueToken(0, 0, SymDict, "{}", args), parent: nil, children: nil, position: posLeaf, priority: priValue, evalFunc: evalDict, } } // -------- dict func func evalDict(ctx ExprContext, self *term) (v any, err error) { dict, _ := self.value().(map[any]*term) items := make(DictType, len(dict)) for key, tree := range dict { var param any if param, err = tree.compute(ctx); err != nil { break } items[key] = param } if err == nil { v = &items } return }