stack

package
v1.4.1 Latest Latest
Warning

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

Go to latest
Published: Jul 27, 2024 License: MIT Imports: 8 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 summing 'a' and 'b'.",
}

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

View Source
var Arccosine = &Action{
	func(so *StackOperator) (toPrint string, err error) {
		f := so.Stack.Pop()
		if f < -1 || f > 1 {
			return "", so.Fail("cannot take arccosine of number less than -1 or greater than 1", f)
		}
		so.Stack.Push(math.Acos(f))
		return so.Stack.Display(), nil
	}, 1, 1,
	"Pop 'a'; push the arccosine of 'a' in radians.",
}

Arccosine is an Action with the following description: Pop 'a'; push the arccosine of 'a' in radians.

View Source
var Arcsine = &Action{
	func(so *StackOperator) (toPrint string, err error) {
		f := so.Stack.Pop()
		if f < -1 || f > 1 {
			return "", so.Fail("cannot take arcsine of number less than -1 or greater than 1", f)
		}
		so.Stack.Push(math.Asin(f))
		return so.Stack.Display(), nil
	}, 1, 1,
	"Pop 'a'; push the arcsine of 'a' in radians.",
}

Arcsine is an Action with the following description: Pop 'a'; push the arcsine of 'a' in radians.

View Source
var Arctangent = &Action{
	func(so *StackOperator) (toPrint string, err error) {
		so.Stack.Push(math.Atan(so.Stack.Pop()))
		return so.Stack.Display(), nil
	}, 1, 1,
	"Pop 'a'; push the argtangent of 'a' in radians.",
}

Arctangent is an Action with the following description: Pop 'a'; push the argtangent of 'a' in radians.

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 dividing 'b' by '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(slices.MaxFunc(so.Actions.List, func(a string, b string) int {
			if len(a) > len(b) {
				return 1
			}
			if len(b) < len(a) {
				return -1
			}
			return 0
		}))
		if maxLen < len(header) {
			maxLen = len(header)
		}
		sb := new(strings.Builder)
		pad := strings.Repeat(" ", maxLen-len(header))
		sb.WriteString(fmt.Sprintf("%s%s | %s\n", pad, header, "description"))
		for k, v, ok := so.Actions.Next(); ok; k, v, ok = so.Actions.Next() {
			if k[0] != 'D' {
				pad := strings.Repeat(" ", maxLen-len(k))
				sb.WriteString(fmt.Sprintf("%s%s : %s\n", pad, k, v.Help))
			}
		}
		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 dividing 'b' by '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 multiplying 'a' and '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 raising 'b' to the power '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 Quit = &Action{
	func(so *StackOperator) (toPrint string, err error) {
		return "", io.EOF
	}, 0, 0,
	"Exit goclacker.",
}
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 subtracting 'a' from 'b'.",
}

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, len(so.Words)+len(so.ValWords))
		i := 0
		for k := range so.Words {
			keys[i] = k
			i++
		}
		for k := range so.ValWords {
			keys[i] = k
			i++
		}
		maxLen := len(slices.MaxFunc(keys,
			func(a string, b string) int {
				if len(a) > len(b) {
					return 1
				}
				if len(a) < len(b) {
					return -1
				}
				return 0
			},
		))
		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)
		for _, k := range keys {
			pad := strings.Repeat(" ", maxLen-len(k))
			val, sep := getWordVal(so, k)
			sb.WriteString(fmt.Sprintf("%s%s %c %s\n", pad, k, sep, val))
		}
		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 {
	List  []K
	Pairs map[K]V
	// contains filtered or unexported fields
}

OrderedMap is a probably really really bad implementation of a map that is ordered... shocking.

func NewOrderedMap added in v1.1.0

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

func (*OrderedMap[K, V]) Delete added in v1.4.0

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

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

func (om *OrderedMap[K, V]) Get(key K) (val V, pres bool)

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

func (om *OrderedMap[K, V]) Next() (key K, val V, ok bool)

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

func (om *OrderedMap[K, V]) Set(key K, val 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
	ValWords    map[string]float64
	Stack       *Stack
	Interactive bool
	Prompt      func() (prompt string)
	ToPrint     []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, Display 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) DefNormWord added in v1.4.0

func (so *StackOperator) DefNormWord(def []string) (msg string, err error)

func (*StackOperator) DefValWord added in v1.4.0

func (so *StackOperator) DefValWord(def []string) (msg string, err error)

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.

func (*StackOperator) ParseWordDef added in v1.4.0

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

ParseWordDef 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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL
JackTT - Gopher 🇻🇳