commit 5cd10237dd040262673cba8660a9a113a8be292a
parent c9837e147e17f77130ae633e2d322888c3290272
Author: Pavel Renev <an2qzavok@gmail.com>
Date: Sun, 17 Oct 2021 21:22:23 +0000
add more builtins
Diffstat:
M | dForth.go | | | 141 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------- |
1 file changed, 96 insertions(+), 45 deletions(-)
diff --git a/dForth.go b/dForth.go
@@ -9,11 +9,15 @@ import (
var le = binary.LittleEndian
const (
- stpt = 0
- rspt = 4
+ pcpt = 0
+ stpt = 4
+ rspt = 8
+ lwpt = 12
+ dtpt = 16
stackstart = 64
rstackstart = 512
- initmemsize = 1024
+ dictstart = 1024
+ initmemsize = 4096
)
type Word struct {
@@ -41,9 +45,21 @@ type Forth struct {
func NewForth() *Forth {
forth := new(Forth)
forth.Dict = make([]*Word, 0)
+ forth.Dict = append(forth.Dict,
+ NewWord("_read", forth.biRead),
+ NewWord("_call", forth.biCall),
+ NewWord("_lit", forth.biLit),
+ NewWord("_jump", forth.BiJump),
+ NewWord(".", forth.biDot),
+ NewWord("@", forth.biFetch),
+ NewWord("!", forth.biStore),
+ )
forth.Mem = make([]byte, initmemsize)
_ = forth.memStore(stpt, stackstart)
_ = forth.memStore(rspt, rstackstart)
+ _ = forth.memStore(dtpt, dictstart)
+ _ = forth.memStore(lwpt, 0)
+ _ = forth.memStore(pcpt, dictstart)
return forth
}
@@ -96,70 +112,105 @@ func (forth *Forth) Pop(pt int32) int32 {
return val
}
-func (forth *Forth) Run() {
+func (forth *Forth) biDot() error {
+ val := forth.Pop(stpt)
+ fmt.Print(val, " ")
+ return nil
+}
+
+func (forth *Forth) biFetch() error {
+ addr := forth.Pop(stpt)
+ val, err := forth.memFetch(addr)
+ if err == nil {
+ forth.Push(stpt, val)
+ }
+ return err
+}
+
+func (forth *Forth) biStore() error {
+ addr := forth.Pop(stpt)
+ val := forth.Pop(stpt)
+ err := forth.memStore(addr, val)
+ return err
+}
+
+func (forth *Forth) biRead() error {
var (
err, nerr error
s string
i, id, num int
w *Word
)
- for err = nil; err == nil; _, err = fmt.Scan(&s) {
- /* We shouldn't get empty reads, but on 9front
- * we somehow do. (as of 18.10.2012)
- * Let's filter them out.
- */
- if s == "" {
- continue
+ if _, err = fmt.Scan(&s); err != nil {
+ return err
+ }
+ /* We shouldn't get empty reads, but on 9front
+ * we somehow do. (as of 18.10.2021)
+ * Let's filter them out.
+ */
+ if s == "" {
+ return nil
+ }
+ id = -1
+ for i, w = range forth.Dict {
+ if (s == w.Name) {
+ id = i
+ break;
}
- id = -1
- for i, w = range forth.Dict {
- if (s == w.Name) {
- id = i
- break;
- }
+ }
+ if id >= 0 {
+ if w.Builtin != nil {
+ w.Builtin()
}
- if id >= 0 {
- if w.Builtin != nil {
- w.Builtin()
- }
- // else exec code
+ // else exec code
+ } else {
+ if num, nerr = strconv.Atoi(s); nerr != nil {
+ fmt.Println("?")
} else {
- if num, nerr = strconv.Atoi(s); nerr != nil {
- fmt.Println("?")
- } else {
- forth.Push(stpt, int32(num))
- }
+ forth.Push(stpt, int32(num))
}
}
+ return nil
}
-func (forth *Forth) biDot() error {
- val := forth.Pop(stpt)
- fmt.Print(val)
- return nil
+func (forth *Forth) biCall() error {
+ /* do we need call?
+ * can we just treat opcode as call
+ * if it's >= dictstart ?
+ */
+ pc, err := forth.memFetch(pcpt)
+ if err != nil {
+ return err
+ }
+ forth.Push(rspt, pc + 1)
+ jmp := forth.Pop(stpt)
+ err = forth.memStore(pcpt, jmp)
+ return err
}
-func (forth *Forth) biFetch() error {
- addr := forth.Pop(stpt)
- val, err := forth.memFetch(addr)
- if err == nil {
- forth.Push(stpt, val)
+func (forth *Forth) biLit() error {
+ pc, err := forth.memFetch(pcpt)
+ if err != nil {
+ return err
}
+ val, err := forth.memFetch(pc)
+ forth.Push(val)
return err
}
-func (forth *Forth) biStore() error {
- addr := forth.Pop(stpt)
- val := forth.Pop(stpt)
- err := forth.memStore(addr, val)
+func (forth *Forth) biJump() error {
+ var err error
+ cond := forth.Pop()
+ addr := forth.Pop()
+ if cond == 0 {
+ err = forth.memStore(pcpt, addr)
+ }
return err
}
func main() {
- fmt.Println("Welcome to dForth")
+ fmt.Println("Welcome to dForth.")
forth := NewForth()
- forth.Dict = append(forth.Dict, NewWord(".", forth.biDot))
- forth.Dict = append(forth.Dict, NewWord("@", forth.biFetch))
- forth.Dict = append(forth.Dict, NewWord("!", forth.biStore))
- forth.Run()
+ for forth.biRead() == nil {
+ }
}