expr/operator-dot.go

62 lines
1.3 KiB
Go

// Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
// All rights reserved.
// operator-dot.go
package expr
// -------- 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 !isInteger(rightValue) {
err = indexTerm.Errorf("index expression must be integer, got %T", rightValue)
return
}
index64, _ := rightValue.(int64)
index := int(index64)
if isList(leftValue) {
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) {
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 {
err = self.errIncompatibleTypes(leftValue, rightValue)
}
return
}
// init
func init() {
registerTermConstructor(SymDot, newDotTerm)
}