// 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, opTerm *term) (v any, err error) {
	var leftValue, rightValue any

	if err = opTerm.checkOperands(); err != nil {
		return
	}
	if leftValue, err = opTerm.children[0].compute(ctx); err != nil {
		return
	}

	indexTerm := opTerm.children[1]

	switch unboxedValue := leftValue.(type) {
	case ExtIterator:
		if indexTerm.symbol() == SymVariable /*|| indexTerm.symbol() == SymString */ {
			opName := indexTerm.source()
			if unboxedValue.HasOperation(opName) {
				v, err = unboxedValue.CallOperation(opName, map[string]any{})
			} else {
				err = indexTerm.Errorf("this iterator do not support the %q command", opName)
				v = false
			}
		} else {
			err = indexTerm.tk.ErrorExpectedGot("identifier")
		}
	default:
		if rightValue, err = opTerm.children[1].compute(ctx); err == nil {
			err = opTerm.errIncompatibleTypes(leftValue, rightValue)
		}
	}
	return
}

// init
func init() {
	registerTermConstructor(SymDot, newDotTerm)
}