adapted and enhanced the dict operations to make them compatible with the new DictType

This commit is contained in:
Celestino Amoroso 2024-05-19 01:38:07 +02:00
parent d6a1607041
commit 24a25bbf94
6 changed files with 111 additions and 20 deletions

View File

@ -102,3 +102,49 @@ func TestDictParser(t *testing.T) {
} }
t.Logf("%s -- test count: %d, succeeded: %d, failed: %d", section, len(inputs), succeeded, failed) t.Logf("%s -- test count: %d, succeeded: %d, failed: %d", section, len(inputs), succeeded, failed)
} }
func TestDictToStringMultiLine(t *testing.T) {
var good bool
section := "dict-ToString-ML"
want := `{
"first": 1
}`
args := map[any]*term{
"first": newLiteralTerm(NewValueToken(0, 0, SymInteger, "1", 1)),
}
dict := newDict(args)
got := dict.ToString(MultiLine)
// fmt.Printf("got=%q\n", got)
if good = got == want; !good {
t.Errorf("ToString(MultiLine): got = %q, want %q", got, want)
}
if good {
t.Logf("%s -- succeeded", section)
} else {
t.Logf("%s -- failed", section)
}
}
func TestDictToString(t *testing.T) {
var good bool
section := "dict-ToString-SL"
want := `{"first": 1}`
args := map[any]*term{
"first": newLiteralTerm(NewValueToken(0, 0, SymInteger, "1", 1)),
}
dict := newDict(args)
got := dict.ToString(0)
// fmt.Printf("got=%q\n", got)
if good = got == want; !good {
t.Errorf("ToString(0): got = %q, want %q", got, want)
}
if good {
t.Logf("%s -- succeeded", section)
} else {
t.Logf("%s -- failed", section)
}
}

View File

@ -22,7 +22,7 @@ func TestExpr(t *testing.T) {
/* 3 */ {`f=openFile("test-file.txt"); line=readFile(f); closeFile(f); line`, "uno", nil}, /* 3 */ {`f=openFile("test-file.txt"); line=readFile(f); closeFile(f); line`, "uno", nil},
/* 4 */ {`mynot=func(v){int(v)?{true}::{false}}; mynot(0)`, true, nil}, /* 4 */ {`mynot=func(v){int(v)?{true}::{false}}; mynot(0)`, true, nil},
/* 5 */ {`1 ? {1} : [1+0] {3*(1+1)}`, int64(6), nil}, /* 5 */ {`1 ? {1} : [1+0] {3*(1+1)}`, int64(6), nil},
/* 10 */ {` /* 6 */ {`
ds={ ds={
"init":func(end){@end=end; @current=0 but true}, "init":func(end){@end=end; @current=0 but true},
"current":func(){current}, "current":func(){current},

View File

@ -12,18 +12,24 @@ import (
type DictType map[any]any type DictType map[any]any
func newDict(dictAny []any) (dict *DictType) { func newDict(dictAny map[any]*term) (dict *DictType) {
var d DictType
if dictAny != nil { if dictAny != nil {
d := make(DictType, len(dictAny)) d = make(DictType, len(dictAny))
for i, item := range dictAny { for i, item := range dictAny {
d[i] = item d[i] = item
} }
dict = &d } else {
d = make(DictType)
} }
dict = &d
return return
} }
func (dict *DictType) toMultiLine(sb *strings.Builder, indent int) { func (dict *DictType) toMultiLine(sb *strings.Builder, indent int) {
sb.WriteString(strings.Repeat("\t", indent))
sb.WriteString("{\n")
first := true first := true
for name, value := range *dict { for name, value := range *dict {
if first { if first {
@ -35,13 +41,13 @@ func (dict *DictType) toMultiLine(sb *strings.Builder, indent int) {
sb.WriteString(strings.Repeat("\t", indent+1)) sb.WriteString(strings.Repeat("\t", indent+1))
if key, ok := name.(string); ok { if key, ok := name.(string); ok {
sb.WriteString(key) sb.WriteString(string('"') + key + string('"'))
} else { } else {
sb.WriteString(fmt.Sprintf("%v", name)) sb.WriteString(fmt.Sprintf("%v", name))
} }
sb.WriteString(": ") sb.WriteString(": ")
if f, ok := value.(Formatter); ok { if f, ok := value.(Formatter); ok {
sb.WriteString(f.ToString(0)) sb.WriteString(f.ToString(MultiLine))
} else if _, ok = value.(Functor); ok { } else if _, ok = value.(Functor); ok {
sb.WriteString("func(){}") sb.WriteString("func(){}")
} else { } else {
@ -49,18 +55,42 @@ func (dict *DictType) toMultiLine(sb *strings.Builder, indent int) {
} }
} }
sb.WriteString(strings.Repeat("\t", indent)) sb.WriteString(strings.Repeat("\t", indent))
sb.WriteString("\n}\n") sb.WriteString("\n}")
} }
func (dict *DictType) ToString(opt FmtOpt) string { func (dict *DictType) ToString(opt FmtOpt) string {
var sb strings.Builder var sb strings.Builder
if opt&MultiLine != 0 { if opt&MultiLine != 0 {
dict.toMultiLine(&sb, 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() return sb.String()
} }
func (dict *DictType) hasKey(d map[any]any, target any) (ok bool) { func (dict *DictType) hasKey(target any) (ok bool) {
for key := range *dict { for key := range *dict {
if ok = reflect.DeepEqual(key, target); ok { if ok = reflect.DeepEqual(key, target); ok {
break break
@ -69,6 +99,22 @@ func (dict *DictType) hasKey(d map[any]any, target any) (ok bool) {
return 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 // -------- dict term
func newDictTerm(args map[any]*term) *term { func newDictTerm(args map[any]*term) *term {
return &term{ return &term{
@ -84,7 +130,7 @@ func newDictTerm(args map[any]*term) *term {
// -------- dict func // -------- dict func
func evalDict(ctx ExprContext, self *term) (v any, err error) { func evalDict(ctx ExprContext, self *term) (v any, err error) {
dict, _ := self.value().(map[any]*term) dict, _ := self.value().(map[any]*term)
items := make(map[any]any, len(dict)) items := make(DictType, len(dict))
for key, tree := range dict { for key, tree := range dict {
var param any var param any
if param, err = tree.compute(ctx); err != nil { if param, err = tree.compute(ctx); err != nil {
@ -93,7 +139,7 @@ func evalDict(ctx ExprContext, self *term) (v any, err error) {
items[key] = param items[key] = param
} }
if err == nil { if err == nil {
v = items v = &items
} }
return return
} }

View File

@ -59,11 +59,11 @@ func evalDot(ctx ExprContext, self *term) (v any, err error) {
if index, err = verifyIndex(ctx, indexTerm, len(unboxedValue)); err == nil { if index, err = verifyIndex(ctx, indexTerm, len(unboxedValue)); err == nil {
v = string(unboxedValue[index]) v = string(unboxedValue[index])
} }
case map[any]any: case *DictType:
var ok bool var ok bool
var indexValue any var indexValue any
if indexValue, err = indexTerm.compute(ctx); err == nil { if indexValue, err = indexTerm.compute(ctx); err == nil {
if v, ok = unboxedValue[indexValue]; !ok { if v, ok = (*unboxedValue)[indexValue]; !ok {
err = fmt.Errorf("key %v does not belong to the dictionary", rightValue) err = fmt.Errorf("key %v does not belong to the dictionary", rightValue)
} }
} }

View File

@ -30,8 +30,9 @@ func evalLength(ctx ExprContext, self *term) (v any, err error) {
s, _ := childValue.(string) s, _ := childValue.(string)
v = int64(len(s)) v = int64(len(s))
} else if IsDict(childValue) { } else if IsDict(childValue) {
m, _ := childValue.(map[any]any) // m, _ := childValue.(map[any]any)
v = int64(len(m)) m, _ := childValue.(*DictType)
v = int64(len(*m))
} else if it, ok := childValue.(Iterator); ok { } else if it, ok := childValue.(Iterator); ok {
if extIt, ok := childValue.(ExtIterator); ok && extIt.HasOperation(countName) { if extIt, ok := childValue.(ExtIterator); ok && extIt.HasOperation(countName) {
count, _ := extIt.CallOperation(countName, nil) count, _ := extIt.CallOperation(countName, nil)

View File

@ -62,12 +62,10 @@ func evalPlus(ctx ExprContext, self *term) (v any, err error) {
v, err = sumAnyFract(leftValue, rightValue) v, err = sumAnyFract(leftValue, rightValue)
} }
} else if IsDict(leftValue) && IsDict(rightValue) { } else if IsDict(leftValue) && IsDict(rightValue) {
leftDict, _ := leftValue.(map[any]any) leftDict, _ := leftValue.(*DictType)
rightDict, _ := rightValue.(map[any]any) rightDict, _ := rightValue.(*DictType)
c := CloneMap(leftDict) c := leftDict.clone()
for key, value := range rightDict { c.merge(rightDict)
c[key] = value
}
v = c v = c
} else { } else {
err = self.errIncompatibleTypes(leftValue, rightValue) err = self.errIncompatibleTypes(leftValue, rightValue)