stack

package
v1.3.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 30, 2024 License: MIT Imports: 7 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var Add = &Action{
	func(so *StackOperator) (toPrint string, err error) {
		so.Stack.Push(so.Stack.Pop() + so.Stack.Pop())
		return so.Stack.Display(), nil
	},
	2, 1,
	"pop 'a', 'b'; push the result of 'a' + 'b'",
}

Add is an Action with the following description: pop 'a', 'b'; push the result of 'a' + 'b'

View Source
var Average = &Action{
	func(so *StackOperator) (toPrint string, err error) {
		n := float64(len(so.Stack.Values))
		Sum.Call(so)
		so.Stack.Push(so.Stack.Pop() / n)
		return so.Stack.Display(), nil
	}, 1, 1,
	"pop all values in the stack; push their average",
}

Average is an Action with the following description: pop all values in the stack; push their average.

View Source
var Ceiling = &Action{
	func(so *StackOperator) (string, error) {
		so.Stack.Push(math.Ceil(so.Stack.Pop()))
		return so.Stack.Display(), nil
	}, 1, 1,
	"pop 'a'; push the least integer value greater than or equal to 'a'",
}

Ceiling is an Action with the following description: pop 'a'; push the least integer value greater than or equal to 'a'.

View Source
var Clear = &Action{
	func(so *StackOperator) (string, error) {
		var c byte
		n := len(so.Stack.Values)
		if n != 1 {
			c = 's'
		}
		so.Stack.Values = make([]float64, 0, cap(so.Stack.Values))
		return fmt.Sprintf("cleared %d value%c\n", n, c), nil
	}, 0, 0,
	"pop all values in the stack",
}

Clear is an Action with the following description: pop all values in the stack.

View Source
var ClearScreen = &Action{
	func(so *StackOperator) (string, error) {
		return "\x1b[2J\x1b[H", nil
	}, 0, 0,
	"clear the terminal screen",
}

ClearScreen is an Action with the following description: clear the terminal screen.

View Source
var Clip = &Action{
	func(so *StackOperator) (toPrint string, err error) {
		c := cap(so.Stack.Values)
		so.Stack.Values = slices.Clip(so.Stack.Values)
		return fmt.Sprintf("clipped %d capacity\n", c-cap(so.Stack.Values)), nil
	}, 0, 0,
	"DEBUG; clip unused stack capacity",
}
View Source
var Cosine = &Action{
	func(so *StackOperator) (string, error) {
		so.Stack.Push(math.Cos(so.Stack.Pop()))
		return so.Stack.Display(), nil
	}, 1, 1,
	"pop 'a'; push the cosine of 'a' in radians",
}

Cosine is an Action with the following description: pop 'a'; push the cosine of 'a' in radians.

View Source
var Degrees = &Action{
	func(so *StackOperator) (string, error) {
		so.Stack.Push(so.Stack.Pop() * 180 / math.Pi)
		return so.Stack.Display(), nil
	}, 1, 1,
	"pop 'a'; push the result of converting 'a' from radians to degrees",
}

Degrees is an Action with the following description: pop 'a'; push the result of converting 'a' from radians to degrees.

View Source
var Display = &Action{
	func(so *StackOperator) (string, error) {
		sBuf := make([]string, len(so.Stack.Values))
		for i, f := range so.Stack.Values {
			sBuf[i] = fmt.Sprint(f)
		}
		return fmt.Sprintf("[ %s ]\n", strings.Join(sBuf, " ")), nil
	}, 0, 0,
	"display all values in the stack",
}

Display is an Action with the following description: display all values in the stack.

View Source
var Divide = &Action{
	func(so *StackOperator) (string, error) {
		divisor := so.Stack.Pop()
		if divisor == 0 {
			return "", so.Fail("cannot divide by 0", divisor)
		}
		so.Stack.Push(so.Stack.Pop() / divisor)
		return so.Stack.Display(), nil
	}, 2, 1,
	"pop 'a', 'b'; push the result of 'b' / 'a'",
}

Divide is an Action with the following description: pop 'a', 'b'; push the result of 'b' / 'a'

View Source
var Factorial = &Action{
	func(so *StackOperator) (string, error) {
		x := so.Stack.Pop()
		if x != float64(int(x)) {
			return "", so.Fail("cannot take factorial of non-integer", x)
		}
		if x < 0 {
			return "", so.Fail("cannot take factorial of negative number", x)
		}
		p := 1
		for i := 2; i <= int(x); i++ {
			p *= i
		}
		so.Stack.Push(float64(p))
		return so.Stack.Display(), nil
	}, 1, 1,
	"pop 'a'; push the factorial of 'a'",
}

Factorial is an Action with the following description: pop 'a'; push the factorial of 'a'.

View Source
var Fill = &Action{
	func(so *StackOperator) (toPrint string, err error) {
		for i := 0; i < cap(so.Stack.Values); i++ {
			if i > len(so.Stack.Values)-1 {
				so.Stack.Values = append(so.Stack.Values, float64(rand.Intn(255)))
			}
		}
		return so.Stack.Display(), nil
	}, 0, 0,
	"DEBUG; fill stack with random values",
}

Fill is an Action with the following description: DEBUG: fill stack with random values

View Source
var Floor = &Action{
	func(so *StackOperator) (string, error) {
		so.Stack.Push(math.Floor(so.Stack.Pop()))
		return so.Stack.Display(), nil
	}, 1, 1,
	"pop 'a'; push the greatest integer value less than or equal to 'a'",
}

Floor is an Action with the following description: pop 'a'; push the greatest integer value less than or equal to 'a'.

View Source
var Froll = &Action{
	func(so *StackOperator) (string, error) {
		newVals := make([]float64, 0, cap(so.Stack.Values))
		l := len(so.Stack.Values)
		newVals = append(newVals, so.Stack.Values[l-1])
		for _, f := range so.Stack.Values[:l-1] {
			newVals = append(newVals, f)
		}
		so.Stack.Values = newVals
		return so.Stack.Display(), nil
	}, 2, 2,
	"roll the stack to the right one position",
}

Froll is an Action with the following description: roll the stack to the right one position.

View Source
var Grow = &Action{
	func(so *StackOperator) (toPrint string, err error) {
		if cap(so.Stack.Values) == 0 {
			so.Stack.Values = slices.Grow(so.Stack.Values, 1)
			return fmt.Sprintf("new stack capacity is %d\n", cap(so.Stack.Values)), nil
		}
		if len(so.Stack.Values) == 0 {
			return "", nil
		}
		n := so.Stack.Pop()
		if n != float64(int(n)) {
			return "", so.Fail("cannot grow stack by non-integer value", n)
		}
		if n < 0 {
			return "", so.Fail("cannot grow stack by negative value", n)
		}
		so.Stack.Push(n)
		so.Stack.Values = slices.Grow(so.Stack.Values, int(n))
		return fmt.Sprintf("new stack capacity is %d\n", cap(so.Stack.Values)), nil
	}, 0, 0,
	"DEBUG; pop 'a'; push 'a'; grow stack to accomadate 'a' more values",
}

Grow is an Action with the following description: DEBUG: pop 'a'; push 'a'; grow stack to accomadate 'a' more values. Will commit blasphemy and grow stack by 1 if cap(Stack.Values) == 0.

View Source
var Help = &Action{
	func(so *StackOperator) (string, error) {
		header := "operator"
		maxLen := len(header)
		for p := so.Actions.Next(); p != nil; p = so.Actions.Next() {
			if len(p.Key) > maxLen {
				maxLen = len(p.Key)
			}
		}
		so.Actions.Reset()
		sb := new(strings.Builder)
		pad := strings.Repeat(" ", maxLen-len(header))
		sb.WriteString(fmt.Sprintf("%s%s | %s\n", pad, header, "description"))
		for p := so.Actions.Next(); p != nil; p = so.Actions.Next() {
			pad := strings.Repeat(" ", maxLen-len(p.Key))
			sb.WriteString(fmt.Sprintf("%s%s : %s\n", pad, p.Key, p.Value.Help))
		}
		so.Actions.Reset()
		return sb.String(), nil
	}, 0, 0,
	"display this information screen",
}

Help is an Action with the following description: display this information screen.

View Source
var Ln = &Action{
	func(so *StackOperator) (string, error) {
		x := so.Stack.Pop()
		if x <= 0 {
			return "", so.Fail("cannot take logarithm of non-positive number", x)
		}
		so.Stack.Push(math.Log(x))
		return so.Stack.Display(), nil
	}, 1, 1,
	"pop 'a'; push the natural logarithm of 'a'",
}

Ln is an Action with the following description: pop 'a'; push the natural logarithm of 'a'.

View Source
var Log = &Action{
	func(so *StackOperator) (string, error) {
		x := so.Stack.Pop()
		if x <= 0 {
			return "", so.Fail("cannot take logarithm of non-positive number", x)
		}
		so.Stack.Push(math.Log10(x))
		return so.Stack.Display(), nil
	}, 1, 1,
	"pop 'a'; push the logarithm base 10 of 'a'",
}

Log is an Action with the following description: pop 'a'; push the logarithm base 10 of 'a'.

View Source
var Modulo = &Action{
	func(so *StackOperator) (string, error) {
		divisor := so.Stack.Pop()
		if divisor == 0 {
			return "", so.Fail("cannot divide by 0", divisor)
		}
		so.Stack.Push(math.Mod(so.Stack.Pop(), divisor))
		return so.Stack.Display(), nil
	}, 2, 1,
	"pop 'a', 'b'; push the remainder of 'b' / 'a'",
}

Modulo is an Action with the following description: pop 'a', 'b'; push the remainder of 'b' / 'a'.

View Source
var Multiply = &Action{
	func(so *StackOperator) (string, error) {
		so.Stack.Push(so.Stack.Pop() * so.Stack.Pop())
		return so.Stack.Display(), nil
	}, 2, 1,
	"pop 'a', 'b'; push the result of 'a' * 'b'",
}

Multiply is an Action with the following description: pop 'a', 'b'; push the result of 'a' * 'b'

View Source
var Pop = &Action{
	func(so *StackOperator) (string, error) {
		so.Stack.Pop()
		return so.Stack.Display(), nil
	}, 1, 0,
	"pop 'a'",
}

Pop is an Action with the following description: pop 'a'.

View Source
var Power = &Action{
	func(so *StackOperator) (string, error) {
		exponent := so.Stack.Pop()
		base := so.Stack.Pop()
		if base == 0 && exponent < 0 {
			return "", so.Fail("cannot raise 0 to negative power", base, exponent)
		}
		if base < 0 && exponent != float64(int(exponent)) {
			return "", so.Fail("cannot raise negative number to non-integer power", base, exponent)
		}
		so.Stack.Push(math.Pow(base, exponent))
		return so.Stack.Display(), nil
	}, 2, 1,
	"pop 'a', 'b'; push the result of 'b' ^ 'a'",
}

Power is an Action with the following description: pop 'a', 'b'; push the result of 'b' ^ 'a'.

View Source
var Pull = &Action{
	func(so *StackOperator) (string, error) {
		so.Stack.Push(so.Stack.Stash)
		return so.Stack.Display(), nil
	}, 0, 1,
	"push the value in the stash",
}

Pull is an Action with the following description: push the value in the stash.

View Source
var Radians = &Action{
	func(so *StackOperator) (string, error) {
		so.Stack.Push(so.Stack.Pop() * math.Pi / 180)
		return so.Stack.Display(), nil
	}, 1, 1,
	"pop 'a'; push the result of converting 'a' from degrees to radians",
}

Radians is an Action with the following description: pop 'a'; push the result of converting 'a' from degrees to radians.

View Source
var Random = &Action{
	func(so *StackOperator) (string, error) {
		so.Stack.Push(rand.Float64())
		return so.Stack.Display(), nil
	}, 0, 1,
	"push a random number between 0 and 1",
}

Random is an Action with the following description: push a random number between 0 and 1.

View Source
var Round = &Action{
	func(so *StackOperator) (string, error) {
		precision := so.Stack.Pop()
		if precision < 0 || precision != float64(int(precision)) {
			return "", so.Fail("precision must be non-negative integer")
		}
		ratio := math.Pow(10, precision)
		so.Stack.Push(math.Round(so.Stack.Pop()*ratio) / ratio)
		return so.Stack.Display(), nil
	}, 2, 1,
	"pop 'a', 'b'; push the result of rounding 'b' to 'a' decimal places",
}

Round is an Action with the following description: pop 'a', 'b'; push the result of rounding 'b' to 'a' decimal places.

View Source
var Rroll = &Action{
	func(so *StackOperator) (string, error) {
		newVals := make([]float64, 0, cap(so.Stack.Values))
		for _, f := range so.Stack.Values[1:] {
			newVals = append(newVals, f)
		}
		newVals = append(newVals, so.Stack.Values[0])
		so.Stack.Values = newVals
		return so.Stack.Display(), nil
	}, 2, 2,
	"roll the stack to the left one position",
}

Rroll is an Action with the following description: roll the stack to the left one position.

View Source
var Sine = &Action{
	func(so *StackOperator) (string, error) {
		so.Stack.Push(math.Sin(so.Stack.Pop()))
		return so.Stack.Display(), nil
	}, 1, 1,
	"pop 'a'; push the sine of 'a' in radians",
}

Sine is an Action with the following description: pop 'a'; push the sine of 'a' in radians.

View Source
var Stash = &Action{
	func(so *StackOperator) (string, error) {
		so.Stack.Stash = so.Stack.Pop()
		return so.Stack.Display(), nil
	}, 1, 0,
	"pop 'a'; stash 'a'",
}

Stash is an Action with the following description: pop 'a'; stash 'a'.

View Source
var Subtract = &Action{
	func(so *StackOperator) (string, error) {
		x := so.Stack.Pop()
		y := so.Stack.Pop()
		so.Stack.Push(y - x)
		return so.Stack.Display(), nil
	}, 2, 1,
	"pop 'a', 'b'; push the result of 'b' - 'a'",
}

Subtract is an Action with the following description:

View Source
var Sum = &Action{
	func(so *StackOperator) (toPrint string, err error) {
		var sum float64
		for len(so.Stack.Values) > 0 {
			sum += so.Stack.Pop()
		}
		so.Stack.Push(sum)
		return so.Stack.Display(), nil
	}, 1, 1,
	"pop all values in the stack; push their sum",
}

Sum is an Action with the following description: pop all values in the stack; push their sum.

View Source
var Swap = &Action{
	func(so *StackOperator) (string, error) {
		x := so.Stack.Pop()
		y := so.Stack.Pop()
		so.Stack.Push(x)
		so.Stack.Push(y)
		return so.Stack.Display(), nil
	}, 2, 2,
	"pop 'a', 'b'; push 'b', 'a'",
}

Swap is an Action with the following description: pop 'a', 'b'; push 'b', 'a'.

View Source
var Tangent = &Action{
	func(so *StackOperator) (string, error) {
		so.Stack.Push(math.Tan(so.Stack.Pop()))
		return so.Stack.Display(), nil
	}, 1, 1,
	"pop 'a'; push the tangent of 'a' in radians",
}

Tangent is an Action with the following description: pop 'a'; push the tangent of 'a' in radians.

View Source
var Words = &Action{
	func(so *StackOperator) (string, error) {
		keys := make([]string, 0, len(so.Words))
		header := "word"
		maxLen := len(header)
		for k := range so.Words {
			keys = append(keys, k)
			if len(k) > maxLen {
				maxLen = len(k)
			}
		}
		slices.SortFunc(keys, func(a string, b string) int {
			if len(a) > len(b) {
				return -1
			}
			if len(a) < len(b) {
				return 1
			}
			if a > b {
				return 1
			}
			if a < b {
				return -1
			}
			return 0
		})
		sb := new(strings.Builder)
		pad := strings.Repeat(" ", maxLen-len(header))
		sb.WriteString(fmt.Sprintf("%s%s | definition\n", pad, header))
		for _, k := range keys {
			pad := strings.Repeat(" ", maxLen-len(k))
			sb.WriteString(fmt.Sprintf("%s%s : %s\n", pad, k, so.Words[k]))
		}
		return sb.String(), nil
	}, 0, 0,
	"display all defined words",
}

Words is an Action with the following description: display all defined words.

Functions

This section is empty.

Types

type Action

type Action struct {

	// Pops represents how many values a call to action will take from the
	// stack.
	Pops int
	// Pushes represents how many values a call to action will add to the stack.
	Pushes int
	// Help describes the purpose of the action.
	Help string
	// contains filtered or unexported fields
}

func (*Action) Call

func (a *Action) Call(so *StackOperator) (toPrint string, err error)

Call calls the function stored in action and returns the string and error value returned by that function

type OrderedMap added in v1.1.0

type OrderedMap[K comparable, V any] struct {
	Pairs map[K]*Pair[K, V]

	Current int
	// contains filtered or unexported fields
}

OrderedMap contains a generic map of values, and an auxilary list to get items from in an ordered fashion.

func NewOrderedMap added in v1.1.0

func NewOrderedMap[K comparable, V any]() *OrderedMap[K, V]

NewOrderedMap returns a pointer to an OrderedMap with initialized values that is ready to use.

func (*OrderedMap[K, V]) Get added in v1.1.0

func (om *OrderedMap[K, V]) Get(key K) (pair *Pair[K, V], present bool)

Get returns the Pair at OrderedMap[key], and whether key is present in the OrderedMap.

func (*OrderedMap[K, V]) Next added in v1.1.0

func (om *OrderedMap[K, V]) Next() (pair *Pair[K, V])

Next returns the next Pair in OrderedMap sequentially, from the first one set to the last.

for p := om.Next(); p != nil; p = om.next() {...}

func (*OrderedMap[K, V]) Reset added in v1.1.0

func (om *OrderedMap[K, V]) Reset()

Reset sets the value of OrderedMap.Current to 0.

func (*OrderedMap[K, V]) Set added in v1.1.0

func (om *OrderedMap[K, V]) Set(key K, val V)

Set sets OrderedMap[key] = Pair{Key: key, Value: val} and panics if the key is already present in the OrderedMap.

type Pair added in v1.1.0

type Pair[K comparable, V any] struct {
	Key   K
	Value V
}

Pair contains a Key of type K and Value of type V.

type Stack

type Stack struct {
	Values []float64
	Stash  float64

	// Expandable signifies whether stack capacity can be increased or not.
	Expandable bool
	// contains filtered or unexported fields
}

Stack contains a slice of float64 and methods to operate on that slice.

func (*Stack) Display

func (stk *Stack) Display() string

Display returns a string of all values in the stack according to Stack.displayFmt

func (*Stack) Pop

func (stk *Stack) Pop() float64

Pop removes the last value in Stack.Values and returns the value removed.

func (*Stack) Push

func (stk *Stack) Push(f float64) error

Push attempts to append f to Stack.Values and returns an error if the stack is at capacity.

type StackOperator

type StackOperator struct {
	Actions     *OrderedMap[string, *Action]
	Words       map[string]string
	Stack       *Stack
	Interactive bool
	Prompt      func() (prompt string)
	PrintBuf    []byte
	// contains filtered or unexported fields
}

StackOperator contains a map for converting string tokens into operations that can be called to operate on the stack.

func NewStackOperator

func NewStackOperator(actions *OrderedMap[string, *Action], maxStack int, interactive bool, noDisplay bool, strict bool) *StackOperator

NewStackOperator returns a pointer to a new StackOperator, initialized to given arguments and a default set of defined words and formatters.

func (*StackOperator) DefWord

func (so *StackOperator) DefWord(def []string) (message string, err error)

DefWord adds a word to StackOperator.Words with the key being def[0] and the value being the rest of the slice. It deletes def[0] from StackOperator.Words if len(def) == 1. It returns a string and nil if the operator was successful and an empty string and an error if not.

func (*StackOperator) ExecuteToken

func (so *StackOperator) ExecuteToken(token string) (toPrint string, err error)

ExecuteToken determines if `token` is an Action token or defined word and executes it accordingly. Returns the string and error from doing what it needs to do.

func (*StackOperator) Fail

func (so *StackOperator) Fail(message string, values ...float64) error

Fail pushes all values to the stack and returns an error containing `message`. It also prints Stack.Display if the StackOperator is interactive

func (*StackOperator) MakePromptFunc

func (so *StackOperator) MakePromptFunc(format string, fmtChar byte) error

MakePromptFunc sets the StackOperator.prompt value that will execute any functions needed to build the prompt and will return a new string every time it is called. This function returns an error if it could not make the prompt function (should always return nil).

func (*StackOperator) ParseInput

func (so *StackOperator) ParseInput(input string) (err error)

ParseInput splits an input string into words and interprets each word as a token. It stops executing tokens if it encounters an '=' or the execution of the token returns an error, and returns that error. ParseInput fills PrintBuf with the message returned by the execution of the last token.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL