expr/operator-prod.go

172 lines
3.9 KiB
Go
Raw Normal View History

2024-03-26 08:45:18 +01:00
// Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
// All rights reserved.
2024-03-26 07:00:53 +01:00
// operator-prod.go
package expr
import (
"errors"
"strings"
)
//-------- multiply term
func newMultiplyTerm(tk *Token) (inst *term) {
return &term{
2024-04-09 05:32:50 +02:00
tk: *tk,
// class: classOperator,
// kind: kindUnknown,
2024-03-26 07:00:53 +01:00
children: make([]*term, 0, 2),
position: posInfix,
priority: priProduct,
evalFunc: evalMultiply,
}
}
func evalMultiply(ctx ExprContext, self *term) (v any, err error) {
2024-03-26 07:00:53 +01:00
var leftValue, rightValue any
if leftValue, rightValue, err = self.evalInfix(ctx); err != nil {
return
}
if IsString(leftValue) && IsInteger(rightValue) {
2024-03-26 07:00:53 +01:00
s, _ := leftValue.(string)
n, _ := rightValue.(int64)
v = strings.Repeat(s, int(n))
} else if isNumOrFract(leftValue) && isNumOrFract(rightValue) {
if IsFloat(leftValue) || IsFloat(rightValue) {
2024-03-26 07:00:53 +01:00
v = numAsFloat(leftValue) * numAsFloat(rightValue)
} else if isFraction(leftValue) || isFraction(rightValue) {
v, err = mulAnyFract(leftValue, rightValue)
2024-03-26 07:00:53 +01:00
} else {
leftInt, _ := leftValue.(int64)
rightInt, _ := rightValue.(int64)
v = leftInt * rightInt
}
} else {
err = self.errIncompatibleTypes(leftValue, rightValue)
}
return
}
//-------- divide term
func newDivideTerm(tk *Token) (inst *term) {
return &term{
2024-04-09 05:32:50 +02:00
tk: *tk,
// class: classOperator,
// kind: kindUnknown,
2024-03-26 07:00:53 +01:00
children: make([]*term, 0, 2),
position: posInfix,
priority: priProduct,
evalFunc: evalDivide,
}
}
func evalDivide(ctx ExprContext, self *term) (v any, err error) {
2024-03-26 07:00:53 +01:00
var leftValue, rightValue any
if leftValue, rightValue, err = self.evalInfix(ctx); err != nil {
return
}
if isNumOrFract(leftValue) && isNumOrFract(rightValue) {
if IsFloat(leftValue) || IsFloat(rightValue) {
2024-03-26 07:00:53 +01:00
d := numAsFloat(rightValue)
if d == 0.0 {
err = errors.New("division by zero")
} else {
v = numAsFloat(leftValue) / d
}
} else if isFraction(leftValue) || isFraction(rightValue) {
v, err = divAnyFract(leftValue, rightValue)
2024-03-26 07:00:53 +01:00
} else {
leftInt, _ := leftValue.(int64)
if rightInt, _ := rightValue.(int64); rightInt == 0 {
err = errors.New("division by zero")
} else {
v = leftInt / rightInt
}
}
} else {
err = self.errIncompatibleTypes(leftValue, rightValue)
}
return
}
//-------- divide as float term
func newDivideAsFloatTerm(tk *Token) (inst *term) {
return &term{
tk: *tk,
children: make([]*term, 0, 2),
position: posInfix,
priority: priProduct,
evalFunc: evalDivideAsFloat,
}
}
func evalDivideAsFloat(ctx ExprContext, self *term) (v any, err error) {
var leftValue, rightValue any
if leftValue, rightValue, err = self.evalInfix(ctx); err != nil {
return
}
if isNumOrFract(leftValue) && isNumOrFract(rightValue) {
d := numAsFloat(rightValue)
if d == 0.0 {
err = errors.New("division by zero")
} else {
v = numAsFloat(leftValue) / d
}
} else {
err = self.errIncompatibleTypes(leftValue, rightValue)
}
return
}
//-------- reminder term
func newReminderTerm(tk *Token) (inst *term) {
return &term{
2024-04-09 05:32:50 +02:00
tk: *tk,
// class: classOperator,
// kind: kindUnknown,
children: make([]*term, 0, 2),
position: posInfix,
priority: priProduct,
evalFunc: evalReminder,
}
}
func evalReminder(ctx ExprContext, self *term) (v any, err error) {
var leftValue, rightValue any
if leftValue, rightValue, err = self.evalInfix(ctx); err != nil {
return
}
if IsInteger(leftValue) && IsInteger(rightValue) {
rightInt, _ := rightValue.(int64)
if rightInt == 0 {
err = errors.New("division by zero")
} else {
leftInt, _ := leftValue.(int64)
v = leftInt % rightInt
}
} else {
err = self.errIncompatibleTypes(leftValue, rightValue)
}
return
}
2024-03-26 07:00:53 +01:00
// init
func init() {
registerTermConstructor(SymStar, newMultiplyTerm)
registerTermConstructor(SymSlash, newDivideTerm)
registerTermConstructor(SymDotSlash, newDivideAsFloatTerm)
registerTermConstructor(SymPercent, newReminderTerm)
2024-03-26 07:00:53 +01:00
}