aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDimitri Sokolyuk <demon@dim13.org>2018-01-14 00:27:48 +0100
committerDimitri Sokolyuk <demon@dim13.org>2018-01-14 00:27:48 +0100
commit8a566444c4e3e75977bbb1629891b3fe594c3069 (patch)
treeb939b4fd54e60be213b60553df4ef84247dfd850
parent2ed31b4befe7d971da594dc33be0954a0b56d743 (diff)
non-blocking io
-rw-r--r--cmd/eval/main.go2
-rw-r--r--cmd/j1e/main.go2
-rw-r--r--eval.go68
-rw-r--r--eval_test.go2
4 files changed, 56 insertions, 18 deletions
diff --git a/cmd/eval/main.go b/cmd/eval/main.go
index 8d85a6f..b9518f3 100644
--- a/cmd/eval/main.go
+++ b/cmd/eval/main.go
@@ -7,5 +7,5 @@ func main() {
if err := vm.LoadFile("testdata/j1e.bin"); err != nil {
panic(err)
}
- vm.Eval()
+ vm.Run()
}
diff --git a/cmd/j1e/main.go b/cmd/j1e/main.go
index 1d4c7ff..65cf626 100644
--- a/cmd/j1e/main.go
+++ b/cmd/j1e/main.go
@@ -7,5 +7,5 @@ import "dim13.org/j1"
func main() {
vm := j1.New()
vm.LoadBytes(J1eBin)
- vm.Eval()
+ vm.Run()
}
diff --git a/eval.go b/eval.go
index 70426da..b40af46 100644
--- a/eval.go
+++ b/eval.go
@@ -18,11 +18,17 @@ type J1 struct {
d stack
r stack
console io.ReadWriter
- done bool
+ done chan struct{}
+ in, out chan uint16
}
func New() *J1 {
- return &J1{console: NewConsole()}
+ return &J1{
+ console: NewConsole(),
+ done: make(chan struct{}),
+ in: make(chan uint16, 1),
+ out: make(chan uint16, 1),
+ }
}
// Reset VM
@@ -48,15 +54,49 @@ func (j1 *J1) LoadFile(fname string) error {
return j1.LoadBytes(data)
}
-// Eval evaluates content of memory
-func (j1 *J1) Eval() {
- for !j1.done {
- ins := Decode(j1.memory[j1.pc])
- //fmt.Printf("%v\n%v", ins, j1)
- j1.eval(ins)
+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() {
+ for {
+ select {
+ case <-j1.done:
+ return
+ default:
+ ins := Decode(j1.memory[j1.pc])
+ //fmt.Printf("%v\n%v", ins, j1)
+ j1.Eval(ins)
+ }
}
}
+// 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())
@@ -70,9 +110,9 @@ func (j1 *J1) writeAt(addr, value uint16) {
}
switch addr {
case 0xf000: // key
- fmt.Fprintf(j1.console, "%c", value)
+ j1.out <- value
case 0xf002: // bye
- j1.done = true
+ close(j1.done)
}
}
@@ -82,16 +122,14 @@ func (j1 *J1) readAt(addr uint16) uint16 {
}
switch addr {
case 0xf000: // tx!
- var b uint16
- fmt.Fscanf(j1.console, "%c", &b)
- return b
+ return <-j1.in
case 0xf001: // ?rx
- return 1
+ return uint16(len(j1.in))
}
return 0
}
-func (j1 *J1) eval(ins Instruction) {
+func (j1 *J1) Eval(ins Instruction) {
j1.pc++
switch v := ins.(type) {
case Lit:
diff --git a/eval_test.go b/eval_test.go
index 60d3e1b..96d111e 100644
--- a/eval_test.go
+++ b/eval_test.go
@@ -114,7 +114,7 @@ func TestEval(t *testing.T) {
t.Run(fmt.Sprint(tc.ins), func(t *testing.T) {
state := New()
for _, ins := range tc.ins {
- state.eval(ins)
+ state.Eval(ins)
}
cmp(t, *state, tc.end)
})