adapted and enhanced the dict operations to make them compatible with the new DictType
This commit is contained in:
parent
d6a1607041
commit
24a25bbf94
46
dict_test.go
46
dict_test.go
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -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},
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
Loading…
Reference in New Issue
Block a user