diff --git a/builtins.go b/builtins.go index fac4261..a5692b2 100644 --- a/builtins.go +++ b/builtins.go @@ -7,6 +7,9 @@ import ( "os" ) +var FALSE = 0 +var TRUE = -1 + // Builtins is a handy holder for our various default words type Builtins struct{} @@ -61,10 +64,10 @@ func (b *Builtins) Eq(s *Stack) func() error { return err } if tos == nos { - s.Push(-1) + s.Push(TRUE) return nil } - s.Push(0) + s.Push(FALSE) return nil } } @@ -81,10 +84,10 @@ func (b *Builtins) NEq(s *Stack) func() error { return err } if tos != nos { - s.Push(-1) + s.Push(TRUE) return nil } - s.Push(0) + s.Push(FALSE) return nil } } @@ -100,11 +103,11 @@ func (b *Builtins) Lt(s *Stack) func() error { if err != nil { return err } - if tos < nos { - s.Push(-1) + if nos < tos { + s.Push(TRUE) return nil } - s.Push(0) + s.Push(FALSE) return nil } } @@ -120,11 +123,11 @@ func (b *Builtins) Gt(s *Stack) func() error { if err != nil { return err } - if tos > nos { - s.Push(-1) + if nos > tos { + s.Push(TRUE) return nil } - s.Push(0) + s.Push(FALSE) return nil } } @@ -140,11 +143,11 @@ func (b *Builtins) LtEq(s *Stack) func() error { if err != nil { return err } - if tos <= nos { - s.Push(-1) + if nos <= tos { + s.Push(TRUE) return nil } - s.Push(0) + s.Push(FALSE) return nil } } @@ -160,11 +163,11 @@ func (b *Builtins) GtEq(s *Stack) func() error { if err != nil { return err } - if tos >= nos { - s.Push(-1) + if nos >= tos { + s.Push(TRUE) return nil } - s.Push(0) + s.Push(FALSE) return nil } } @@ -233,6 +236,39 @@ func (b *Builtins) Div(s *Stack) func() error { } } +// Mod performs NOS%TOS and pushes the (integer!) modulo result +func (b *Builtins) Mod(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 + } + s.Push(nos % tos) + return nil + } +} + +// DivMod performs NOS/TOS & NOS%TOS and pushes the (integer!) results: TOS as quotient, NOS as remainder +func (b *Builtins) DivMod(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 + } + s.Push(nos % tos) + s.Push(nos / tos) + return nil + } +} + // Print pops the stack and outputs it to the writer with a trailing space (defaults to stdout) func (b *Builtins) Print(out io.Writer, s *Stack) func() error { if out == nil { @@ -418,13 +454,13 @@ func (b *Builtins) If(s *Stack, i *Stack) func() error { if err != nil { return err } - // TOS was 0, don't execute this branch - if tos == 0 { + // TOS was FALSE, don't execute this branch + if tos == FALSE { i.Push(0) - } else { - // TOS wasn't 0, execute until we see ELSE/THEN - i.Push(1) + return nil } + // TOS wasn't 0, execute until we see ELSE/THEN + i.Push(1) return nil } } diff --git a/main.go b/main.go index ecec366..d55857c 100644 --- a/main.go +++ b/main.go @@ -39,6 +39,11 @@ func main() { dict.AddWord("-", Word{Name: "-", Impl: b.Sub(&stack)}) dict.AddWord("*", Word{Name: "*", Impl: b.Mul(&stack)}) dict.AddWord("/", Word{Name: "/", Impl: b.Div(&stack)}) + dict.AddWord("MOD", Word{Name: "MOD", Impl: b.Mod(&stack)}) + dict.AddWord("/MOD", Word{Name: "/MOD", Impl: b.DivMod(&stack)}) + dict.AddWord("+1", Word{Name: "+1", Source: []string{"1", "+"}}) + dict.AddWord("-1", Word{Name: "-1", Source: []string{"1", "-"}}) + dict.AddWord("ABS", Word{Name: "ABS", Source: []string{"DUP 0< IF DUP DUP - SWAP - THEN"}}) // output dict.AddWord(".", Word{Name: ".", Impl: b.Print(os.Stdout, &stack)}) dict.AddWord("EMIT", Word{Name: "EMIT", Impl: b.Emit(os.Stdout, &stack)}) @@ -47,6 +52,7 @@ func main() { dict.AddWord("=", Word{Name: "=", Impl: b.Eq(&stack)}) dict.AddWord("0=", Word{Name: "0=", Source: []string{"0", "="}}) dict.AddWord("<>", Word{Name: "<>", Impl: b.NEq(&stack)}) + dict.AddWord("0<>", Word{Name: "0<>", Source: []string{"0=", "0="}}) dict.AddWord(">", Word{Name: ">", Impl: b.Gt(&stack)}) dict.AddWord("<", Word{Name: "<", Impl: b.Lt(&stack)}) dict.AddWord(">=", Word{Name: ">=", Impl: b.GtEq(&stack)})