diff --git a/builtins.go b/builtins.go index 5bf339c..055ab49 100644 --- a/builtins.go +++ b/builtins.go @@ -8,18 +8,138 @@ type Builtins struct{} // ErrExit is a special sentinel value to cease computation and quit var ErrExit = fmt.Errorf("exit requested") +// Eq compares TOS and NOS and puts -1 on the stack if they're equal, 0 otherwise. +func (b *Builtins) Eq(s *Stack) func() error { + return func() error { + tos, err := s.Pop() + if err != nil { + return err + } + nos, err := s.Pop() + if err != nil { + return err + } + if tos == nos { + s.Push(-1) + return nil + } + s.Push(0) + return nil + } +} + +// NEq compares TOS and NOS and puts -1 on the stack if they're not equal, 0 otherwise. +func (b *Builtins) NEq(s *Stack) func() error { + return func() error { + tos, err := s.Pop() + if err != nil { + return err + } + nos, err := s.Pop() + if err != nil { + return err + } + if tos != nos { + s.Push(-1) + return nil + } + s.Push(0) + return nil + } +} + +// Lt compares TOS and NOS and puts -1 on the stack if TOS is less than NOS, 0 otherwise. +func (b *Builtins) Lt(s *Stack) func() error { + return func() error { + tos, err := s.Pop() + if err != nil { + return err + } + nos, err := s.Pop() + if err != nil { + return err + } + if tos < nos { + s.Push(-1) + return nil + } + s.Push(0) + return nil + } +} + +// Gt compares TOS and NOS and puts -1 on the stack if TOS is greater than NOS, 0 otherwise. +func (b *Builtins) Gt(s *Stack) func() error { + return func() error { + tos, err := s.Pop() + if err != nil { + return err + } + nos, err := s.Pop() + if err != nil { + return err + } + if tos > nos { + s.Push(-1) + return nil + } + s.Push(0) + return nil + } +} + +// LtEq compares TOS and NOS and puts -1 on the stack if TOS is less than or equal to NOS, 0 otherwise. +func (b *Builtins) LtEq(s *Stack) func() error { + return func() error { + tos, err := s.Pop() + if err != nil { + return err + } + nos, err := s.Pop() + if err != nil { + return err + } + if tos <= nos { + s.Push(-1) + return nil + } + s.Push(0) + return nil + } +} + +// GtEq compares TOS and NOS and puts -1 on the stack if TOS is greater than or equal to NOS, 0 otherwise. +func (b *Builtins) GtEq(s *Stack) func() error { + return func() error { + tos, err := s.Pop() + if err != nil { + return err + } + nos, err := s.Pop() + if err != nil { + return err + } + if tos >= nos { + s.Push(-1) + return nil + } + s.Push(0) + return nil + } +} + // 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() + tos, err := s.Pop() if err != nil { return err } - r2, err := s.Pop() + nos, err := s.Pop() if err != nil { return err } - s.Push(r1 + r2) + s.Push(tos + nos) return nil } } @@ -27,15 +147,15 @@ func (b *Builtins) Add(s *Stack) func() error { // Sub performs NOS - TOS and pushes the result func (b *Builtins) Sub(s *Stack) func() error { return func() error { - r1, err := s.Pop() + tos, err := s.Pop() if err != nil { return err } - r2, err := s.Pop() + nos, err := s.Pop() if err != nil { return err } - s.Push(r2 - r1) + s.Push(nos - tos) return nil } } @@ -43,15 +163,15 @@ func (b *Builtins) Sub(s *Stack) func() error { // 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() + tos, err := s.Pop() if err != nil { return err } - r2, err := s.Pop() + nos, err := s.Pop() if err != nil { return err } - s.Push(r2 * r1) + s.Push(nos * tos) return nil } } @@ -59,15 +179,15 @@ func (b *Builtins) Mul(s *Stack) func() error { // Div performs NOS/TOS and pushes the (integer!) result func (b *Builtins) Div(s *Stack) func() error { return func() error { - r1, err := s.Pop() + tos, err := s.Pop() if err != nil { return err } - r2, err := s.Pop() + nos, err := s.Pop() if err != nil { return err } - s.Push(r2 / r1) + s.Push(nos / tos) return nil } } @@ -75,11 +195,11 @@ func (b *Builtins) Div(s *Stack) func() error { // Print pops the stack and outputs it to stdout func (b *Builtins) Print(s *Stack) func() error { return func() error { - r1, err := s.Pop() + tos, err := s.Pop() if err != nil { return err } - fmt.Print(r1, " ") + fmt.Print(tos, " ") return nil } } @@ -87,12 +207,12 @@ func (b *Builtins) Print(s *Stack) func() error { // 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() + tos, err := s.Pop() if err != nil { return err } - s.Push(r1) - s.Push(r1) + s.Push(tos) + s.Push(tos) return nil } } @@ -100,16 +220,16 @@ func (b *Builtins) Dup(s *Stack) func() error { // Swap inverts the order of TOS and NOS func (b *Builtins) Swap(s *Stack) func() error { return func() error { - r1, err := s.Pop() + tos, err := s.Pop() if err != nil { return err } - r2, err := s.Pop() + nos, err := s.Pop() if err != nil { return err } - s.Push(r1) - s.Push(r2) + s.Push(tos) + s.Push(nos) return nil } } @@ -117,17 +237,17 @@ func (b *Builtins) Swap(s *Stack) func() error { // 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() + tos, err := s.Pop() if err != nil { return err } - r2, err := s.Pop() + nos, err := s.Pop() if err != nil { return err } - s.Push(r2) - s.Push(r1) - s.Push(r2) + s.Push(nos) + s.Push(tos) + s.Push(nos) return nil } } @@ -143,21 +263,21 @@ func (b *Builtins) Drop(s *Stack) func() error { // 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() + tos, err := s.Pop() if err != nil { return err } - r2, err := s.Pop() + nos, err := s.Pop() if err != nil { return err } - r3, err := s.Pop() + p3, err := s.Pop() if err != nil { return err } - s.Push(r2) - s.Push(r1) - s.Push(r3) + s.Push(nos) + s.Push(tos) + s.Push(p3) return err } } @@ -175,11 +295,11 @@ func (b *Builtins) Words(d Dictionary) func() error { // Emit outputs the UTF-8 rune for the int on the top of the stack func (b *Builtins) Emit(s *Stack) func() error { return func() error { - i, err := s.Pop() + tos, err := s.Pop() if err != nil { return err } - fmt.Print(string(rune(i)) + " ") + fmt.Print(string(rune(tos)) + " ") return nil } } @@ -187,11 +307,11 @@ func (b *Builtins) Emit(s *Stack) func() error { // ToR pops from the stack to the return stack func (b *Builtins) ToR(s *Stack, r *Stack) func() error { return func() error { - r1, err := s.Pop() + tos, err := s.Pop() if err != nil { return err } - r.Push(r1) + r.Push(tos) return nil } } @@ -199,11 +319,11 @@ func (b *Builtins) ToR(s *Stack, r *Stack) func() error { // RFrom pops from the return stack to the stack func (b *Builtins) RFrom(s *Stack, r *Stack) func() error { return func() error { - r1, err := r.Pop() + tors, err := r.Pop() if err != nil { return err } - s.Push(r1) + s.Push(tors) return nil } } @@ -211,12 +331,12 @@ func (b *Builtins) RFrom(s *Stack, r *Stack) func() error { // RFetch copies from the return stack to the stack func (b *Builtins) RFetch(s *Stack, r *Stack) func() error { return func() error { - r1, err := r.Pop() + tors, err := r.Pop() if err != nil { return err } - r.Push(r1) - s.Push(r1) + r.Push(tors) + s.Push(tors) return nil } } diff --git a/main.go b/main.go index 42b5eeb..ba5df59 100644 --- a/main.go +++ b/main.go @@ -19,6 +19,13 @@ func main() { dict.AddWord("*", b.Mul(&stack), "") dict.AddWord("/", b.Div(&stack), "") dict.AddWord(".", b.Print(&stack), "") + dict.AddWord("=", b.Eq(&stack), "") + dict.AddWord("0=", nil, "0 = ") + dict.AddWord("<>", b.NEq(&stack), "") + dict.AddWord(">", b.Gt(&stack), "") + dict.AddWord("<", b.Lt(&stack), "") + dict.AddWord(">=", b.GtEq(&stack), "") + dict.AddWord("<=", b.LtEq(&stack), "") dict.AddWord("DUP", b.Dup(&stack), "") dict.AddWord("SWAP", b.Swap(&stack), "") dict.AddWord("OVER", b.Over(&stack), "")