implement EMIT and QUIT

This commit is contained in:
David 2021-02-13 21:37:56 -05:00
parent 4dc64947db
commit bce7e3df4e
2 changed files with 29 additions and 1 deletions

View File

@ -5,6 +5,9 @@ import "fmt"
// Builtins is a handy holder for our various default words // Builtins is a handy holder for our various default words
type Builtins struct{} type Builtins struct{}
// ErrExit is a special sentinel value to cease computation and quit
var ErrExit = fmt.Errorf("exit requested")
// 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 {
@ -169,6 +172,18 @@ 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()
if err != nil {
return err
}
fmt.Print(string(rune(i)) + " ")
return nil
}
}
// CR prints a newline to standard out // CR prints a newline to standard out
func (b *Builtins) CR() func() error { func (b *Builtins) CR() func() error {
return func() error { return func() error {
@ -177,6 +192,13 @@ func (b *Builtins) CR() func() error {
} }
} }
// Quit exits the repl
func (b *Builtins) Quit() func() error {
return func() error {
return ErrExit
}
}
// Debug prints the stack without modifying it // Debug prints the stack without modifying it
func (b *Builtins) Debug(s *Stack) func() error { func (b *Builtins) Debug(s *Stack) func() error {
return func() error { return func() error {

View File

@ -2,6 +2,7 @@ package main
import ( import (
"bufio" "bufio"
"errors"
"fmt" "fmt"
"os" "os"
"strings" "strings"
@ -24,7 +25,9 @@ func main() {
dict.AddWord("ROT", b.Rot(&stack), "") dict.AddWord("ROT", b.Rot(&stack), "")
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("CR", b.CR(), "") dict.AddWord("CR", b.CR(), "")
dict.AddWord("QUIT", b.Quit(), "")
c := Context{ c := Context{
Dictionary: dict, Dictionary: dict,
@ -45,7 +48,10 @@ func main() {
} }
line = strings.TrimSpace(line) line = strings.TrimSpace(line)
err = c.Eval(line + " ") // append a space to make sure we always close out our parse loop err = c.Eval(line + " ") // append a space to make sure we always close out our parse loop
if err != nil { if errors.Is(err, ErrExit) {
fmt.Printf("bye\n")
os.Exit(0)
} else if err != nil {
fmt.Printf("error in evaluation: %v\n", err) fmt.Printf("error in evaluation: %v\n", err)
} }
fmt.Print("ok") fmt.Print("ok")