go-calc/calc/calc.go

184 lines
4.6 KiB
Go
Raw Permalink Normal View History

2024-02-21 10:42:56 +00:00
package calc
import (
"gitea.zaclys.com/bvaudour/gob/number"
"gitea.zaclys.com/bvaudour/gob/option"
)
type Calc struct {
stack Stack
registry Registry
macro Macro
}
type CalcFunc func(*Calc) option.Option[error]
type IntCalcFunc[N integer] func(...N) CalcFunc
type WordCalcFunc func(string) CalcFunc
type CalcErrFunc func(*Calc) []error
func New() *Calc {
return &Calc{
registry: make(Registry),
macro: make(Macro),
}
}
func (c *Calc) SetPrecision(precision option.Option[uint64], fix option.Option[bool]) {
if p, ok := precision.Get(); ok {
number.FloatingPrecision = p
}
if f, ok := fix.Get(); ok {
number.FixedPrecision = f
}
}
func (c *Calc) Precision() (precision uint64, fix bool) {
return number.FloatingPrecision, number.FixedPrecision
}
func (c *Calc) Push(numbers ...number.Number) { c.stack.Push(numbers...) }
func (c *Calc) Stack() Stack { return c.stack.Clone() }
func (c *Calc) GetStack() (result option.Result[Stack]) {
if c.stack.IsEmpty() {
result = option.Err[Stack](ErrIsEmpty(errStack))
} else {
result = option.Ok(c.Stack())
}
return
}
func (c *Calc) Len() { c.Push(number.IntOf(c.stack.Len())) }
func (c *Calc) Last() option.Result[number.Number] { return c.stack.Last() }
func (c *Calc) Pop() (err option.Option[error]) {
if e, ok := c.stack.Pop().Err(); ok {
err = option.Some(e)
}
return
}
func (c *Calc) Reset() option.Option[error] { return c.stack.Reset() }
func (c *Calc) Duplicate() option.Option[error] { return c.stack.Duplicate() }
func (c *Calc) DuplicateStack() option.Option[error] { return c.stack.DuplicateAll() }
func (c *Calc) Reverse() option.Option[error] { return c.stack.Reverse() }
func (c *Calc) ReverseStack() option.Option[error] { return c.stack.ReverseAll() }
func (c *Calc) Sort() option.Option[error] { return c.stack.Sort() }
func (c *Calc) SortDesc() option.Option[error] { return c.stack.SortDesc() }
func (c *Calc) Registries() Registry { return c.registry.Clone() }
func (c *Calc) GetRegistries() (result option.Result[Registry]) {
if len(c.registry) == 0 {
result = option.Err[Registry](ErrIsEmpty(errMemory))
} else {
result = option.Ok(c.Registries())
}
return
}
func (c *Calc) Registry(k string) option.Result[Stack] { return c.registry.Get(k) }
func (c *Calc) ResetRegistry(k string) option.Option[error] { return c.registry.Reset(k) }
func (c *Calc) ResetRegistries() option.Option[error] { return c.registry.ResetAll() }
func (c *Calc) Store(k string) (err option.Option[error]) {
pop := c.stack.Pop()
if n, ok := pop.Ok(); ok {
c.registry.Set(k, n)
} else if e, ok := pop.Err(); ok {
err = option.Some(e)
}
return
}
func (c *Calc) StoreStack(k string) (err option.Option[error]) {
if c.stack.IsEmpty() {
err = option.Some(ErrIsEmpty(errStack))
} else {
c.registry.Set(k, c.Stack()...)
c.Reset()
2024-02-21 10:42:56 +00:00
}
return
}
func (c *Calc) Load(k string) (err option.Option[error]) {
result := c.registry.Get(k)
if s, ok := result.Ok(); ok {
c.Push(s...)
} else if e, ok := result.Err(); ok {
err = option.Some(e)
}
return
}
func (c *Calc) Macros() Macro { return c.macro.Clone() }
func (c *Calc) GetMacros() (result option.Result[Macro]) {
if len(c.macro) == 0 {
result = option.Err[Macro](ErrIsEmpty(errMemory))
} else {
result = option.Ok(c.Macros())
}
return
}
func (c *Calc) Macro(k string) (result option.Result[MacroStack]) { return c.macro.Get(k) }
func (c *Calc) StoreMacro(k string, args ...MacroElement) {
c.macro.Set(k, args)
}
func (c *Calc) Exec(s MacroStack) (errors []error) {
for _, e := range s {
if n, ok := e.Left(); ok {
c.Push(n)
} else if f, ok := e.Right(); ok {
if err, ok := f(c).Get(); ok {
errors = append(errors, err)
}
}
}
return
}
func (c *Calc) ExecMacro(k string) (errors []error) {
result := c.macro.Get(k)
if s, ok := result.Ok(); ok {
errors = c.Exec(s)
} else if err, ok := result.Err(); ok {
errors = append(errors, err)
}
return
}
func (c *Calc) ResetMacro(k string) option.Option[error] { return c.macro.Reset(k) }
func (c *Calc) ResetMacros() option.Option[error] { return c.macro.ResetAll() }
func (c *Calc) NoAction() (error option.Option[error]) { return }
func (c *Calc) If(e1, e2 MacroElement) (err option.Option[error]) {
result := c.stack.Pop()
if n, ok := result.Ok(); ok {
if n.IsZero() || n.IsNan() {
if n2, ok := e2.Left(); ok {
c.Push(n2)
} else if c2, ok := e2.Right(); ok {
c2(c)
}
} else if n1, ok := e1.Left(); ok {
c.Push(n1)
} else if c1, ok := e1.Right(); ok {
c1(c)
}
} else if e, ok := result.Err(); ok {
err = option.Some(e)
}
return
}