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:
M | dForth.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)
}
}