2024-04-19 09:05:26 +02:00
|
|
|
// Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
|
|
|
|
// All rights reserved.
|
|
|
|
|
|
|
|
// operator-dot.go
|
|
|
|
package expr
|
|
|
|
|
2024-04-21 14:24:56 +02:00
|
|
|
import "fmt"
|
|
|
|
|
2024-04-19 09:05:26 +02:00
|
|
|
// -------- 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) {
|
2024-04-21 14:24:56 +02:00
|
|
|
var index int
|
|
|
|
if index, err = indexTerm.toInt(rightValue, "index expression value must be integer"); err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2024-04-19 09:05:26 +02:00
|
|
|
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) {
|
2024-04-21 14:24:56 +02:00
|
|
|
var index int
|
|
|
|
if index, err = indexTerm.toInt(rightValue, "index expression value must be integer"); err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2024-04-19 09:05:26 +02:00
|
|
|
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)
|
|
|
|
}
|
2024-04-21 14:24:56 +02:00
|
|
|
} 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)
|
|
|
|
}
|
2024-04-19 09:05:26 +02:00
|
|
|
} else {
|
|
|
|
err = self.errIncompatibleTypes(leftValue, rightValue)
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// init
|
|
|
|
func init() {
|
|
|
|
registerTermConstructor(SymDot, newDotTerm)
|
|
|
|
}
|