// Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com). // All rights reserved. // operator-fact.go package expr import ( "fmt" "git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/scan" ) //-------- fact term func newFactTerm(tk *scan.Token) (inst *scan.Term) { return &scan.Term{ Tk: *tk, Children: make([]*scan.Term, 0, 1), Position: scan.PosPostfix, Priority: scan.PriFact, EvalFunc: evalFact, } } func evalFact(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { var leftValue any if leftValue, err = opTerm.Children[0].Compute(ctx); err != nil { return } if kern.IsInteger(leftValue) { if i, _ := leftValue.(int64); i >= 0 { f := int64(1) for k := int64(1); k <= i; k++ { f *= k } v = f } else { err = fmt.Errorf("factorial of a negative integer (%d) is not allowed", i) } } else { err = opTerm.Errorf("incompatible type for factorial: %s", kern.TypeName(leftValue)) } return } // init func init() { scan.RegisterTermConstructor(scan.SymExclamation, newFactTerm) }