dForth

Forth-like interpreter in go
Log | Files | Refs

commit 959785dc64cb1385268664b73fc7d25f8ae98097
parent b85f968aa25b96bc869a908dc229104d65bde105
Author: Pavel Renev <an2qzavok@gmail.com>
Date:   Sat,  6 Nov 2021 19:00:43 +0000

add words for defining new words

Diffstat:
MdForth.go | 142++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------
1 file changed, 122 insertions(+), 20 deletions(-)

diff --git a/dForth.go b/dForth.go @@ -24,12 +24,14 @@ type Word struct { Name string Builtin func() error Addr int32 + Immediate bool } func NewWord(name string, builtin func() error) *Word { word := new(Word) word.Name = name word.Builtin = builtin + word.Immediate = false return word } @@ -50,6 +52,11 @@ func NewForth() *Forth { NewWord(".", forth.biDot), NewWord("@", forth.biFetch), NewWord("!", forth.biStore), + NewWord("+", forth.biAdd), + NewWord("-", forth.biSub), + NewWord("_nwd", forth.biNewWord), + NewWord("immediate", forth.biImmediate), + NewWord("_cmpl", forth.biCompile), ) forth.Mem = make([]byte, initmemsize) _ = forth.memStore(stpt, stackstart) @@ -58,8 +65,9 @@ func NewForth() *Forth { _ = forth.memStore(lwpt, 0) _ = forth.memStore(pcpt, dictstart) forth.memCompile( - 0, /* _read */ + 0, /* _read */ 2, dictstart, /* _lit dictstart */ + 2, 0, /* _lit 0 */ 3, /* _jump */ ) return forth @@ -94,21 +102,21 @@ func (forth *Forth) memCompile(codes ...int32) { } func (forth *Forth) Step() error { - pc, _ := forth.memFetch(pcpt); + pc, err := forth.memFetch(pcpt); inst, _ := forth.memFetch(pc); - pc++; - if (inst > 0) && (int(inst) < len(forth.Dict)) { - w := forth.Dict[inst] - if w.Builtin != nil { - return w.Builtin() - } else { - pc = w.Addr - } + _ = forth.memStore(pcpt, pc + 4) + if (inst < 0) || (int(inst) > len(forth.Dict)) { + return fmt.Errorf("invalid inst %d, pc %d", + inst, pc) + } + w := forth.Dict[inst] + if w.Builtin != nil { + err = w.Builtin() } else { - return fmt.Errorf("invalid instruction: %d, pc %d", inst, pc - 1); + forth.Push(rspt, pc + 4) + pc = w.Addr } - _ = forth.memStore(pcpt, pc); - return nil + return err } func (forth *Forth) Push(pt, val int32) { @@ -140,6 +148,17 @@ func (forth *Forth) Pop(pt int32) int32 { return val } +func (forth *Forth) Exec(w *Word) error { + if w.Builtin != nil { + return w.Builtin() + } else { + pc, _ := forth.memFetch(pcpt) + forth.Push(rspt, pc) + _ = forth.memStore(pcpt, w.Addr) + } + return nil +} + func (forth *Forth) biDot() error { val := forth.Pop(stpt) fmt.Print(val, " ") @@ -177,20 +196,19 @@ func (forth *Forth) biRead() error { * Let's filter them out. */ if s == "" { + forth.memCompile(4) /* 4 is _ret */ return nil } id = -1 - for i, w = range forth.Dict { + for i = len(forth.Dict); i > 0; i-- { + w = forth.Dict[i - 1] if (s == w.Name) { - id = i + id = i - 1 break; } } if id >= 0 { - if w.Builtin != nil { - w.Builtin() - } - // else exec code + return forth.Exec(w) } else { if num, nerr = strconv.Atoi(s); nerr != nil { fmt.Println("?") @@ -228,6 +246,7 @@ func (forth *Forth) biLit() error { return err } val, err := forth.memFetch(pc) + _ = forth.memStore(pcpt, pc + 4) forth.Push(stpt, val) return err } @@ -242,9 +261,92 @@ func (forth *Forth) biJump() error { return err } +func (forth *Forth) biAdd() error { + x := forth.Pop(stpt) + y := forth.Pop(stpt) + forth.Push(stpt, x + y) + return nil +} + +func (forth *Forth) biSub() error { + x := forth.Pop(stpt) + y := forth.Pop(stpt) + forth.Push(stpt, y - x) + return nil +} + +func (forth *Forth) biNewWord() error { + var ( + err error + s string + w *Word + ) + if _, err = fmt.Scan(&s); err != nil { + return err + } + w = NewWord(s, nil) + w.Addr, _ = forth.memFetch(dtpt) + forth.Dict = append(forth.Dict, w) + forth.Push(stpt, w.Addr) + return nil +} + +func (forth *Forth) biImmediate() error { + forth.Dict[len(forth.Dict) - 1].Immediate = true + return nil +} + +func (forth *Forth) biCompile() error { + var ( + i int + s string + w *Word + ) + s = "" + for ;; { + if _, err := fmt.Scan(&s); err != nil { + return err + } + if s == ";" { + break + } + w = nil + for i = len(forth.Dict); i > 0; i-- { + if s == forth.Dict[i-1].Name { + w = forth.Dict[i-1] + break + } + } + if w != nil { + if w.Immediate { + forth.Exec(w) + } else { + forth.memCompile(int32(i - 1)) + } + } else { + if num, err := strconv.Atoi(s); err != nil { + fmt.Println("?") + /* TODO: we should revert changes to before compilation start */ + return nil + } else { + forth.memCompile(2 , int32(num)) /* 2 is _lit */ + } + } + } + forth.memCompile(4) /* 4 is _ret */ + return nil +} + func main() { + var err error fmt.Println("Welcome to dForth.") forth := NewForth() - for forth.Step() == nil { + for err = nil; err == nil; err = forth.Step() { + } + fmt.Println("done: ", err) + for i := 0; i < 32; i++ { + addr := int32(dictstart + i * 4) + inst, _ := forth.memFetch(addr) + fmt.Println(addr, inst) } }