operator-dot.go: refactoring

This commit is contained in:
Celestino Amoroso 2024-04-27 14:44:52 +02:00
parent 60effe8f1b
commit c99be491df

View File

@ -17,6 +17,20 @@ func newDotTerm(tk *Token) (inst *term) {
}
}
func verifyIndex(indexTerm *term, indexValue any, maxValue int) (index int, err error) {
var v int
if v, err = indexTerm.toInt(indexValue, "index expression value must be integer"); err == nil {
if v >= 0 && v < maxValue {
index = v
} else if index >= -maxValue {
index = maxValue + v
} else {
err = indexTerm.Errorf("index %d out of bounds", v)
}
}
return
}
func evalDot(ctx ExprContext, self *term) (v any, err error) {
var leftValue, rightValue any
@ -26,41 +40,23 @@ func evalDot(ctx ExprContext, self *term) (v any, err error) {
indexTerm := self.children[1]
if isList(leftValue) {
switch unboxedValue := leftValue.(type) {
case []any:
var index int
if index, err = indexTerm.toInt(rightValue, "index expression value must be integer"); err != nil {
return
if index, err = verifyIndex(indexTerm, rightValue, len(unboxedValue)); err == nil {
v = unboxedValue[index]
}
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) {
case string:
var index int
if index, err = indexTerm.toInt(rightValue, "index expression value must be integer"); err != nil {
return
if index, err = verifyIndex(indexTerm, rightValue, len(unboxedValue)); err == nil {
v = unboxedValue[index]
}
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) {
case map[any]any:
var ok bool
d, _ := leftValue.(map[any]any)
if v, ok = d[rightValue]; !ok {
if v, ok = unboxedValue[rightValue]; !ok {
err = fmt.Errorf("key %v does not belong to the dictionary", rightValue)
}
} else {
default:
err = self.errIncompatibleTypes(leftValue, rightValue)
}
return