Compare commits

..

No commits in common. "626e90d54c7c6493601ba5a7a14961ecc7f57fc8" and "199203e73f222c8196e1b4d56fbe5fd3318e3cbb" have entirely different histories.

5 changed files with 44 additions and 90 deletions

View File

@ -286,7 +286,7 @@ func (b *Builtins) Rot(s *Stack) func() error {
func (b *Builtins) Words(d Dictionary) func() error { func (b *Builtins) Words(d Dictionary) func() error {
return func() error { return func() error {
for n := range d { for n := range d {
fmt.Printf("%s %s\n", n, d[n].Source) fmt.Printf("%s ", n)
} }
return nil return nil
} }
@ -341,41 +341,6 @@ func (b *Builtins) RFetch(s *Stack, r *Stack) func() error {
} }
} }
// If checks if NOS != 0 and conditionally executes any following statements if so
func (b *Builtins) If(s *Stack, r *Stack) func() error {
return func() error {
return nil
}
}
// Else executes a separate piece of code if NOS == 0 after an if check
func (b *Builtins) Else(s *Stack, r *Stack) func() error {
return func() error {
return nil
}
}
// Then ends an If/Else block
func (b *Builtins) Then(s *Stack, r *Stack) func() error {
return func() error {
return nil
}
}
// Do sets up a loop
func (b *Builtins) Do(s *Stack, r *Stack) func() error {
return func() error {
return nil
}
}
// Loop closes a loop
func (b *Builtins) Loop(s *Stack, r *Stack) func() error {
return func() error {
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 {

32
eval.go
View File

@ -6,7 +6,7 @@ import (
"strings" "strings"
) )
// Context is a set of Dictionary + Stacks representing a runtime environment // Context is a set of Dictionary + Stack representing a runtime environment
type Context struct { type Context struct {
Dictionary Dictionary Dictionary Dictionary
Stack *Stack Stack *Stack
@ -17,7 +17,6 @@ type Context struct {
func (c *Context) Eval(line string) error { func (c *Context) Eval(line string) error {
// state // state
var word []byte var word []byte
var words []string
var comment bool var comment bool
immediate := true immediate := true
@ -38,27 +37,26 @@ func (c *Context) Eval(line string) error {
if len(word) == 0 { if len(word) == 0 {
if line[i] == ':' { if line[i] == ':' {
immediate = false immediate = false
} else if line[i-1] == ' ' && line[i] == ';' {
c.Dictionary.AddWord(words[0], nil, words[1:])
word = []byte{}
immediate = true
} }
} else { } else {
word = append(word, line[i]) if line[i-1] == ' ' && line[i] == ';' {
def := strings.SplitN(strings.TrimSpace(string(word)), " ", 2)
c.Dictionary.AddWord(def[0], nil, def[1]+" ")
word = []byte{}
immediate = true
} else {
word = append(word, line[i])
}
} }
case ' ': case ' ':
if !immediate { // continue building our subroutine if we're not in immediate mode... if !immediate { // continue building our subroutine if we're not in immediate mode...
if len(word) != 0 { // don't add empty words to our list word = append(word, line[i])
words = append(words, strings.TrimSpace(string(word)))
word = []byte{}
}
continue continue
} }
if len(word) == 0 || comment { if len(word) == 0 || comment {
// empty space, just continue... // empty space, just continue...
continue continue
} }
int, err := strconv.Atoi(string(word)) int, err := strconv.Atoi(string(word))
if err == nil { if err == nil {
// it was a number! put it on the stack. // it was a number! put it on the stack.
@ -66,7 +64,6 @@ func (c *Context) Eval(line string) error {
word = []byte{} word = []byte{}
continue continue
} }
// it wasn't a number. Is it a word we know? // it wasn't a number. Is it a word we know?
w, err := c.Dictionary.GetWord(string(word)) w, err := c.Dictionary.GetWord(string(word))
if err != nil { if err != nil {
@ -79,17 +76,12 @@ func (c *Context) Eval(line string) error {
return err return err
} }
word = []byte{} word = []byte{}
} else if len(w.Source) != 0 { } else if w.Source != "" {
// user-defined word; let's descend... // user-defined word; let's descend...
c.RStack.Push(i) err := c.Eval(w.Source)
err := c.Eval(strings.Join(w.Source, " ") + " ")
if err != nil { if err != nil {
return err return err
} }
i, err = c.RStack.Pop()
if err != nil {
return fmt.Errorf("error while popping from return stack: %v", err)
}
word = []byte{} word = []byte{}
} }
default: default:

57
main.go
View File

@ -14,33 +14,31 @@ func main() {
dict := Dictionary{} dict := Dictionary{}
b := &Builtins{} b := &Builtins{}
dict.AddWord("+", b.Add(&stack), nil) dict.AddWord("+", b.Add(&stack), "")
dict.AddWord("-", b.Sub(&stack), nil) dict.AddWord("-", b.Sub(&stack), "")
dict.AddWord("*", b.Mul(&stack), nil) dict.AddWord("*", b.Mul(&stack), "")
dict.AddWord("/", b.Div(&stack), nil) dict.AddWord("/", b.Div(&stack), "")
dict.AddWord(".", b.Print(&stack), nil) dict.AddWord(".", b.Print(&stack), "")
dict.AddWord("=", b.Eq(&stack), nil) dict.AddWord("=", b.Eq(&stack), "")
dict.AddWord("0=", nil, []string{"0", "="}) dict.AddWord("0=", nil, "0 = ")
dict.AddWord("<>", b.NEq(&stack), nil) dict.AddWord("<>", b.NEq(&stack), "")
dict.AddWord(">", b.Gt(&stack), nil) dict.AddWord(">", b.Gt(&stack), "")
dict.AddWord("<", b.Lt(&stack), nil) dict.AddWord("<", b.Lt(&stack), "")
dict.AddWord(">=", b.GtEq(&stack), nil) dict.AddWord(">=", b.GtEq(&stack), "")
dict.AddWord("<=", b.LtEq(&stack), nil) dict.AddWord("<=", b.LtEq(&stack), "")
dict.AddWord("0<", nil, []string{"0", "<"}) dict.AddWord("DUP", b.Dup(&stack), "")
dict.AddWord("0>", nil, []string{"0", ">"}) dict.AddWord("SWAP", b.Swap(&stack), "")
dict.AddWord("DUP", b.Dup(&stack), nil) dict.AddWord("OVER", b.Over(&stack), "")
dict.AddWord("SWAP", b.Swap(&stack), nil) dict.AddWord("DROP", b.Drop(&stack), "")
dict.AddWord("OVER", b.Over(&stack), nil) dict.AddWord("ROT", b.Rot(&stack), "")
dict.AddWord("DROP", b.Drop(&stack), nil) dict.AddWord("WORDS", b.Words(dict), "")
dict.AddWord("ROT", b.Rot(&stack), nil) dict.AddWord(".S", b.Debug(&stack), "")
dict.AddWord("WORDS", b.Words(dict), nil) dict.AddWord("EMIT", b.Emit(&stack), "")
dict.AddWord(".S", b.Debug(&stack), nil) dict.AddWord("R>", b.RFrom(&stack, &rstack), "")
dict.AddWord("EMIT", b.Emit(&stack), nil) dict.AddWord(">R", b.ToR(&stack, &rstack), "")
dict.AddWord("R>", b.RFrom(&stack, &rstack), nil) dict.AddWord("R@", b.RFetch(&stack, &rstack), "")
dict.AddWord(">R", b.ToR(&stack, &rstack), nil) dict.AddWord("CR", b.CR(), "")
dict.AddWord("R@", b.RFetch(&stack, &rstack), nil) dict.AddWord("QUIT", b.Quit(), "")
dict.AddWord("CR", b.CR(), nil)
dict.AddWord("QUIT", b.Quit(), nil)
c := Context{ c := Context{
Dictionary: dict, Dictionary: dict,
@ -66,9 +64,8 @@ func main() {
fmt.Printf("bye\n") fmt.Printf("bye\n")
os.Exit(0) os.Exit(0)
} else if err != nil { } else if err != nil {
fmt.Printf("error in evaluation: %v", err) fmt.Printf("error in evaluation: %v\n", err)
} else {
fmt.Print("ok")
} }
fmt.Print("ok")
} }
} }

View File

@ -9,11 +9,11 @@ type Dictionary map[string]Word
type Word struct { type Word struct {
Name string Name string
Impl func() error Impl func() error
Source []string Source string
} }
// AddWord inserts a new word into the dictonary, optionally overwriting the existing word // AddWord inserts a new word into the dictonary, optionally overwriting the existing word
func (d Dictionary) AddWord(name string, impl func() error, source []string) { func (d Dictionary) AddWord(name string, impl func() error, source string) {
d[name] = Word{ d[name] = Word{
Name: name, Name: name,
Impl: impl, Impl: impl,

View File

@ -5,7 +5,7 @@ import "testing"
func TestDictionary(t *testing.T) { func TestDictionary(t *testing.T) {
d := Dictionary{} d := Dictionary{}
d.AddWord("INC", nil, []string{"1", "+"}) d.AddWord("INC", nil, "1 + ")
w, err := d.GetWord("INC") w, err := d.GetWord("INC")
if err != nil { if err != nil {
t.Fail() t.Fail()
@ -16,7 +16,7 @@ func TestDictionary(t *testing.T) {
if w.Impl != nil { if w.Impl != nil {
t.Fail() t.Fail()
} }
if len(w.Source) != 2 || w.Source[0] != "1" || w.Source[1] != "+" { if w.Source != "1 +" {
t.Fail() t.Fail()
} }
} }