aboutsummaryrefslogtreecommitdiff
path: root/eval.go
diff options
context:
space:
mode:
Diffstat (limited to 'eval.go')
-rw-r--r--eval.go66
1 files changed, 20 insertions, 46 deletions
diff --git a/eval.go b/eval.go
index b40af46..b22012f 100644
--- a/eval.go
+++ b/eval.go
@@ -2,14 +2,20 @@ package j1
import (
"bytes"
+ "context"
"encoding/binary"
"fmt"
- "io"
"io/ioutil"
)
const memSize = 0x4000
+type Console interface {
+ Read() uint16
+ Write(uint16)
+ Len() uint16
+}
+
// J1 Forth processor VM
type J1 struct {
memory [memSize]uint16 // 0..0x3fff main memory, 0x4000 .. 0x7fff mem-mapped i/o
@@ -17,18 +23,12 @@ type J1 struct {
st0 uint16 // top of data stack
d stack
r stack
- console io.ReadWriter
- done chan struct{}
- in, out chan uint16
+ console Console
+ cancel context.CancelFunc
}
func New() *J1 {
- return &J1{
- console: NewConsole(),
- done: make(chan struct{}),
- in: make(chan uint16, 1),
- out: make(chan uint16, 1),
- }
+ return new(J1)
}
// Reset VM
@@ -54,33 +54,14 @@ func (j1 *J1) LoadFile(fname string) error {
return j1.LoadBytes(data)
}
-func (j1 *J1) read() {
- var b uint16
- for {
- fmt.Fscanf(j1.console, "%c", &b)
- select {
- case <-j1.done:
- return
- case j1.in <- b:
- }
- }
-}
-
-func (j1 *J1) write() {
- for {
- select {
- case <-j1.done:
- return
- case b := <-j1.out:
- fmt.Fprintf(j1.console, "%c", b)
- }
- }
-}
-
-func (j1 *J1) run() {
+// Run evaluates content of memory
+func (j1 *J1) Run() {
+ ctx, cancel := context.WithCancel(context.Background())
+ j1.console = NewConsole(ctx)
+ j1.cancel = cancel
for {
select {
- case <-j1.done:
+ case <-ctx.Done():
return
default:
ins := Decode(j1.memory[j1.pc])
@@ -90,13 +71,6 @@ func (j1 *J1) run() {
}
}
-// Run evaluates content of memory
-func (j1 *J1) Run() {
- go j1.read()
- go j1.write()
- j1.run()
-}
-
func (j1 *J1) String() string {
s := fmt.Sprintf("\tPC=%0.4X ST=%0.4X\n", j1.pc, j1.st0)
s += fmt.Sprintf("\tD=%0.4X\n", j1.d.dump())
@@ -110,9 +84,9 @@ func (j1 *J1) writeAt(addr, value uint16) {
}
switch addr {
case 0xf000: // key
- j1.out <- value
+ j1.console.Write(value)
case 0xf002: // bye
- close(j1.done)
+ j1.cancel()
}
}
@@ -122,9 +96,9 @@ func (j1 *J1) readAt(addr uint16) uint16 {
}
switch addr {
case 0xf000: // tx!
- return <-j1.in
+ return j1.console.Read()
case 0xf001: // ?rx
- return uint16(len(j1.in))
+ return j1.console.Len()
}
return 0
}