the assign operators, '=' and ':=', can set the value of dict items

This commit is contained in:
2026-05-17 07:15:12 +02:00
parent 3ccbeb3978
commit 1bf8015da1
4 changed files with 114 additions and 21 deletions
+46 -16
View File
@@ -7,6 +7,7 @@ package expr
import (
"git.portale-stac.it/go-pkg/expr/kern"
"git.portale-stac.it/go-pkg/expr/scan"
"git.portale-stac.it/go-pkg/expr/util"
)
// -------- dot term
@@ -34,7 +35,7 @@ func evalDot(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
switch unboxedValue := leftValue.(type) {
case kern.ExtIterator:
if indexTerm.Tk.Sym == scan.SymVariable /*|| indexTerm.Tk.Sym == scan.SymString */ {
if indexTerm.Symbol() == scan.SymVariable /*|| indexTerm.Tk.Sym == scan.SymString */ {
opName := indexTerm.Source()
if unboxedValue.HasOperation(opName) {
v, err = unboxedValue.CallOperation(opName, map[string]any{})
@@ -46,21 +47,22 @@ func evalDot(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
err = indexTerm.Tk.ErrorExpectedGot("identifier")
}
case *kern.DictType:
var ok bool
s := opTerm.Children[1].Tk.Sym
if s == scan.SymVariable || s == scan.SymString {
src := opTerm.Children[1].Source()
if len(src) > 1 && src[0] == '"' && src[len(src)-1] == '"' {
src = src[1 : len(src)-1]
}
if v, ok = unboxedValue.GetItem(src); !ok {
err = opTerm.Errorf("key %q not found", src)
}
} else if rightValue, err = opTerm.Children[1].Compute(ctx); err == nil {
if v, ok = unboxedValue.GetItem(rightValue); !ok {
err = opTerm.Errorf("key %q not found", rightValue)
}
}
// var ok bool
// s := opTerm.Children[1].Symbol()
// if s == scan.SymVariable || s == scan.SymString {
// src := opTerm.Children[1].Source()
// if len(src) > 1 && src[0] == '"' && src[len(src)-1] == '"' {
// src = src[1 : len(src)-1]
// }
// if v, ok = unboxedValue.GetItem(src); !ok {
// err = opTerm.Errorf("key %q not found", src)
// }
// } else if rightValue, err = opTerm.Children[1].Compute(ctx); err == nil {
// if v, ok = unboxedValue.GetItem(rightValue); !ok {
// err = opTerm.Errorf("key %q not found", rightValue)
// }
// }
v, err = dotGetDictItemValue(ctx, unboxedValue, opTerm.Children[1])
default:
if rightValue, err = opTerm.Children[1].Compute(ctx); err == nil {
err = opTerm.Errorf("incompatible types: %s and %s", kern.TypeName(leftValue), kern.TypeName(rightValue))
@@ -69,6 +71,34 @@ func evalDot(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
return
}
func dotGetDictItemValue(ctx kern.ExprContext, d *kern.DictType, rightTerm *scan.Term) (v any, err error) {
var ok bool
var rightValue any
s := rightTerm.Symbol()
if s == scan.SymVariable || s == scan.SymString {
// src := rightTerm.Source()
// if len(src) > 1 && src[0] == '"' && src[len(src)-1] == '"' {
// src = src[1 : len(src)-1]
// }
src := util.UnquoteString(rightTerm.Source())
if v, ok = d.GetItem(src); !ok {
err = errDictKeyNotFound(rightTerm, src)
}
} else if rightValue, err = rightTerm.Compute(ctx); err == nil {
if v, ok = d.GetItem(rightValue); !ok {
err = errDictKeyNotFound(rightTerm, rightValue)
}
}
return
}
func errDictKeyNotFound(term *scan.Term, key any) error {
if s, ok := key.(string); ok {
return term.Errorf("key %q not found", s)
}
return term.Errorf("key %v not found", key)
}
// init
func init() {
scan.RegisterTermConstructor(scan.SymDot, newDotTerm)