Compare commits

..

2 Commits

Author SHA1 Message Date
199203e73f add equality checking and lt,gt,etc 2021-02-14 12:20:34 -05:00
7212f3d9f6 add return stack 2021-02-14 11:58:43 -05:00
3 changed files with 204 additions and 34 deletions

View File

@ -8,18 +8,138 @@ type Builtins struct{}
// ErrExit is a special sentinel value to cease computation and quit // ErrExit is a special sentinel value to cease computation and quit
var ErrExit = fmt.Errorf("exit requested") 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 // Add sums the top two numbers on the stack and pushes the result
func (b *Builtins) Add(s *Stack) func() error { func (b *Builtins) Add(s *Stack) func() error {
return func() error { return func() error {
r1, err := s.Pop() tos, err := s.Pop()
if err != nil { if err != nil {
return err return err
} }
r2, err := s.Pop() nos, err := s.Pop()
if err != nil { if err != nil {
return err return err
} }
s.Push(r1 + r2) s.Push(tos + nos)
return nil return nil
} }
} }
@ -27,15 +147,15 @@ func (b *Builtins) Add(s *Stack) func() error {
// Sub performs NOS - TOS and pushes the result // Sub performs NOS - TOS and pushes the result
func (b *Builtins) Sub(s *Stack) func() error { func (b *Builtins) Sub(s *Stack) func() error {
return func() error { return func() error {
r1, err := s.Pop() tos, err := s.Pop()
if err != nil { if err != nil {
return err return err
} }
r2, err := s.Pop() nos, err := s.Pop()
if err != nil { if err != nil {
return err return err
} }
s.Push(r2 - r1) s.Push(nos - tos)
return nil 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 // Mul multiplies the two numbers on the top of the stack and pushes the result
func (b *Builtins) Mul(s *Stack) func() error { func (b *Builtins) Mul(s *Stack) func() error {
return func() error { return func() error {
r1, err := s.Pop() tos, err := s.Pop()
if err != nil { if err != nil {
return err return err
} }
r2, err := s.Pop() nos, err := s.Pop()
if err != nil { if err != nil {
return err return err
} }
s.Push(r2 * r1) s.Push(nos * tos)
return nil return nil
} }
} }
@ -59,15 +179,15 @@ func (b *Builtins) Mul(s *Stack) func() error {
// Div performs NOS/TOS and pushes the (integer!) result // Div performs NOS/TOS and pushes the (integer!) result
func (b *Builtins) Div(s *Stack) func() error { func (b *Builtins) Div(s *Stack) func() error {
return func() error { return func() error {
r1, err := s.Pop() tos, err := s.Pop()
if err != nil { if err != nil {
return err return err
} }
r2, err := s.Pop() nos, err := s.Pop()
if err != nil { if err != nil {
return err return err
} }
s.Push(r2 / r1) s.Push(nos / tos)
return nil return nil
} }
} }
@ -75,11 +195,11 @@ func (b *Builtins) Div(s *Stack) func() error {
// Print pops the stack and outputs it to stdout // Print pops the stack and outputs it to stdout
func (b *Builtins) Print(s *Stack) func() error { func (b *Builtins) Print(s *Stack) func() error {
return func() error { return func() error {
r1, err := s.Pop() tos, err := s.Pop()
if err != nil { if err != nil {
return err return err
} }
fmt.Print(r1, " ") fmt.Print(tos, " ")
return nil 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 // Dup pops the stack, then pushes two copies onto the stack
func (b *Builtins) Dup(s *Stack) func() error { func (b *Builtins) Dup(s *Stack) func() error {
return func() error { return func() error {
r1, err := s.Pop() tos, err := s.Pop()
if err != nil { if err != nil {
return err return err
} }
s.Push(r1) s.Push(tos)
s.Push(r1) s.Push(tos)
return nil return nil
} }
} }
@ -100,16 +220,16 @@ func (b *Builtins) Dup(s *Stack) func() error {
// Swap inverts the order of TOS and NOS // Swap inverts the order of TOS and NOS
func (b *Builtins) Swap(s *Stack) func() error { func (b *Builtins) Swap(s *Stack) func() error {
return func() error { return func() error {
r1, err := s.Pop() tos, err := s.Pop()
if err != nil { if err != nil {
return err return err
} }
r2, err := s.Pop() nos, err := s.Pop()
if err != nil { if err != nil {
return err return err
} }
s.Push(r1) s.Push(tos)
s.Push(r2) s.Push(nos)
return nil return nil
} }
} }
@ -117,17 +237,17 @@ func (b *Builtins) Swap(s *Stack) func() error {
// Over duplicates NOS to TOS, resulting in NOS TOS NOS // Over duplicates NOS to TOS, resulting in NOS TOS NOS
func (b *Builtins) Over(s *Stack) func() error { func (b *Builtins) Over(s *Stack) func() error {
return func() error { return func() error {
r1, err := s.Pop() tos, err := s.Pop()
if err != nil { if err != nil {
return err return err
} }
r2, err := s.Pop() nos, err := s.Pop()
if err != nil { if err != nil {
return err return err
} }
s.Push(r2) s.Push(nos)
s.Push(r1) s.Push(tos)
s.Push(r2) s.Push(nos)
return nil 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 // 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 { func (b *Builtins) Rot(s *Stack) func() error {
return func() error { return func() error {
r1, err := s.Pop() tos, err := s.Pop()
if err != nil { if err != nil {
return err return err
} }
r2, err := s.Pop() nos, err := s.Pop()
if err != nil { if err != nil {
return err return err
} }
r3, err := s.Pop() p3, err := s.Pop()
if err != nil { if err != nil {
return err return err
} }
s.Push(r2) s.Push(nos)
s.Push(r1) s.Push(tos)
s.Push(r3) s.Push(p3)
return err return err
} }
} }
@ -175,11 +295,48 @@ func (b *Builtins) Words(d Dictionary) func() error {
// Emit outputs the UTF-8 rune for the int on the top of the stack // Emit outputs the UTF-8 rune for the int on the top of the stack
func (b *Builtins) Emit(s *Stack) func() error { func (b *Builtins) Emit(s *Stack) func() error {
return func() error { return func() error {
i, err := s.Pop() tos, err := s.Pop()
if err != nil { if err != nil {
return err return err
} }
fmt.Print(string(rune(i)) + " ") fmt.Print(string(rune(tos)) + " ")
return nil
}
}
// ToR pops from the stack to the return stack
func (b *Builtins) ToR(s *Stack, r *Stack) func() error {
return func() error {
tos, err := s.Pop()
if err != nil {
return err
}
r.Push(tos)
return nil
}
}
// RFrom pops from the return stack to the stack
func (b *Builtins) RFrom(s *Stack, r *Stack) func() error {
return func() error {
tors, err := r.Pop()
if err != nil {
return err
}
s.Push(tors)
return nil
}
}
// RFetch copies from the return stack to the stack
func (b *Builtins) RFetch(s *Stack, r *Stack) func() error {
return func() error {
tors, err := r.Pop()
if err != nil {
return err
}
r.Push(tors)
s.Push(tors)
return nil return nil
} }
} }

View File

@ -10,6 +10,7 @@ import (
type Context struct { type Context struct {
Dictionary Dictionary Dictionary Dictionary
Stack *Stack Stack *Stack
RStack *Stack
} }
// Eval evaulates a given line, recursively descending into given words as needed // Eval evaulates a given line, recursively descending into given words as needed

12
main.go
View File

@ -10,6 +10,7 @@ import (
func main() { func main() {
stack := Stack{values: []int{}} stack := Stack{values: []int{}}
rstack := Stack{values: []int{}}
dict := Dictionary{} dict := Dictionary{}
b := &Builtins{} b := &Builtins{}
@ -18,6 +19,13 @@ func main() {
dict.AddWord("*", b.Mul(&stack), "") dict.AddWord("*", b.Mul(&stack), "")
dict.AddWord("/", b.Div(&stack), "") dict.AddWord("/", b.Div(&stack), "")
dict.AddWord(".", b.Print(&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("DUP", b.Dup(&stack), "")
dict.AddWord("SWAP", b.Swap(&stack), "") dict.AddWord("SWAP", b.Swap(&stack), "")
dict.AddWord("OVER", b.Over(&stack), "") dict.AddWord("OVER", b.Over(&stack), "")
@ -26,12 +34,16 @@ func main() {
dict.AddWord("WORDS", b.Words(dict), "") dict.AddWord("WORDS", b.Words(dict), "")
dict.AddWord(".S", b.Debug(&stack), "") dict.AddWord(".S", b.Debug(&stack), "")
dict.AddWord("EMIT", b.Emit(&stack), "") dict.AddWord("EMIT", b.Emit(&stack), "")
dict.AddWord("R>", b.RFrom(&stack, &rstack), "")
dict.AddWord(">R", b.ToR(&stack, &rstack), "")
dict.AddWord("R@", b.RFetch(&stack, &rstack), "")
dict.AddWord("CR", b.CR(), "") dict.AddWord("CR", b.CR(), "")
dict.AddWord("QUIT", b.Quit(), "") dict.AddWord("QUIT", b.Quit(), "")
c := Context{ c := Context{
Dictionary: dict, Dictionary: dict,
Stack: &stack, Stack: &stack,
RStack: &rstack,
} }
reader := bufio.NewReader(os.Stdin) reader := bufio.NewReader(os.Stdin)