// Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com). // All rights reserved. // operator-dot.go package expr import "fmt" // -------- dot term func newDotTerm(tk *Token) (inst *term) { return &term{ tk: *tk, children: make([]*term, 0, 2), position: posInfix, priority: priDot, evalFunc: evalDot, } } func evalDot(ctx ExprContext, self *term) (v any, err error) { var leftValue, rightValue any if leftValue, rightValue, err = self.evalInfix(ctx); err != nil { return } indexTerm := self.children[1] if isList(leftValue) { var index int if index, err = indexTerm.toInt(rightValue, "index expression value must be integer"); err != nil { return } list, _ := leftValue.([]any) if index >= 0 && index < len(list) { v = list[index] } else if index >= -len(list) { v = list[len(list)+index] } else { err = indexTerm.Errorf("index %v out of bounds", index) } } else if isString(leftValue) { var index int if index, err = indexTerm.toInt(rightValue, "index expression value must be integer"); err != nil { return } s, _ := leftValue.(string) if index >= 0 && index < len(s) { v = string(s[index]) } else if index >= -len(s) { v = string(s[len(s)+index]) } else { err = indexTerm.Errorf("index %v out of bounds", index) } } else if isDict(leftValue) { var ok bool d, _ := leftValue.(map[any]any) if v, ok = d[rightValue]; !ok { err = fmt.Errorf("key %v does not belong to the dictionary", rightValue) } } else { err = self.errIncompatibleTypes(leftValue, rightValue) } return } // init func init() { registerTermConstructor(SymDot, newDotTerm) }