187 lines
3.2 KiB
Go
187 lines
3.2 KiB
Go
|
package main
|
||
|
|
||
|
import "fmt"
|
||
|
|
||
|
// Builtins is a handy holder for our various default words
|
||
|
type Builtins struct{}
|
||
|
|
||
|
// Add sums the top two numbers on the stack and pushes the result
|
||
|
func (b *Builtins) Add(s *Stack) func() error {
|
||
|
return func() error {
|
||
|
r1, err := s.Pop()
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
r2, err := s.Pop()
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
s.Push(r1 + r2)
|
||
|
return nil
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Sub performs NOS - TOS and pushes the result
|
||
|
func (b *Builtins) Sub(s *Stack) func() error {
|
||
|
return func() error {
|
||
|
r1, err := s.Pop()
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
r2, err := s.Pop()
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
s.Push(r2 - r1)
|
||
|
return nil
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Mul multiplies the two numbers on the top of the stack and pushes the result
|
||
|
func (b *Builtins) Mul(s *Stack) func() error {
|
||
|
return func() error {
|
||
|
r1, err := s.Pop()
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
r2, err := s.Pop()
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
s.Push(r2 * r1)
|
||
|
return nil
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Div performs NOS/TOS and pushes the (integer!) result
|
||
|
func (b *Builtins) Div(s *Stack) func() error {
|
||
|
return func() error {
|
||
|
r1, err := s.Pop()
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
r2, err := s.Pop()
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
s.Push(r2 / r1)
|
||
|
return nil
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Print pops the stack and outputs it to stdout
|
||
|
func (b *Builtins) Print(s *Stack) func() error {
|
||
|
return func() error {
|
||
|
r1, err := s.Pop()
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
fmt.Print(r1, " ")
|
||
|
return nil
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Dup pops the stack, then pushes two copies onto the stack
|
||
|
func (b *Builtins) Dup(s *Stack) func() error {
|
||
|
return func() error {
|
||
|
r1, err := s.Pop()
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
s.Push(r1)
|
||
|
s.Push(r1)
|
||
|
return nil
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Swap inverts the order of TOS and NOS
|
||
|
func (b *Builtins) Swap(s *Stack) func() error {
|
||
|
return func() error {
|
||
|
r1, err := s.Pop()
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
r2, err := s.Pop()
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
s.Push(r1)
|
||
|
s.Push(r2)
|
||
|
return nil
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Over duplicates NOS to TOS, resulting in NOS TOS NOS
|
||
|
func (b *Builtins) Over(s *Stack) func() error {
|
||
|
return func() error {
|
||
|
r1, err := s.Pop()
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
r2, err := s.Pop()
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
s.Push(r2)
|
||
|
s.Push(r1)
|
||
|
s.Push(r2)
|
||
|
return nil
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Drop simply discards TOS
|
||
|
func (b *Builtins) Drop(s *Stack) func() error {
|
||
|
return func() error {
|
||
|
_, err := s.Pop()
|
||
|
return err
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Rot cycles the first three items on the stack: TOS 1 2 3 -> TOS 3 1 2
|
||
|
func (b *Builtins) Rot(s *Stack) func() error {
|
||
|
return func() error {
|
||
|
r1, err := s.Pop()
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
r2, err := s.Pop()
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
r3, err := s.Pop()
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
s.Push(r2)
|
||
|
s.Push(r1)
|
||
|
s.Push(r3)
|
||
|
return err
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Words outputs a list of all known words in the dictionary
|
||
|
func (b *Builtins) Words(d Dictionary) func() error {
|
||
|
return func() error {
|
||
|
for n := range d {
|
||
|
fmt.Printf("%s ", n)
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// CR prints a newline to standard out
|
||
|
func (b *Builtins) CR() func() error {
|
||
|
return func() error {
|
||
|
fmt.Print("\n")
|
||
|
return nil
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Debug prints the stack without modifying it
|
||
|
func (b *Builtins) Debug(s *Stack) func() error {
|
||
|
return func() error {
|
||
|
fmt.Print(s.values, " ")
|
||
|
return nil
|
||
|
}
|
||
|
}
|