Skip to content

Commit

Permalink
vm: remove dependency on package github.com/pkg/errors
Browse files Browse the repository at this point in the history
  • Loading branch information
db47h committed Aug 4, 2016
1 parent 82e1c42 commit 6491b8c
Show file tree
Hide file tree
Showing 7 changed files with 133 additions and 103 deletions.
5 changes: 1 addition & 4 deletions cmd/retro/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import (
"os"

"github.com/db47h/ngaro/vm"
"github.com/pkg/errors"
)

var fileName = flag.String("image", "retroImage", "Use `filename` as the image to load")
Expand Down Expand Up @@ -103,9 +102,7 @@ func main() {
if err != nil {
return
}
err = proc.Run()
// filter out EOF
if e := errors.Cause(err); e == io.EOF {
if err = proc.Run(); err == io.EOF {
err = nil
}
}
3 changes: 0 additions & 3 deletions vm/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@

package vm

import "github.com/pkg/errors"

// Opcode represents an Ngaro VM opcode.
type Opcode Cell

Expand Down Expand Up @@ -99,7 +97,6 @@ func (i *Instance) Run() (err error) {
if err, ok = e.(error); !ok {
panic(e)
}
err = errors.Wrap(err, "VM abort")
}
}()
i.insCount = 0
Expand Down
103 changes: 103 additions & 0 deletions vm/example_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
// This file is part of ngaro - https://github.com/db47h/ngaro
//
// Copyright 2016 Denis Bernard <db047h@gmail.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package vm_test

import (
"bufio"
"bytes"
"fmt"
"io"
"os"
"strings"

"github.com/db47h/ngaro/vm"
)

// Shows how to load an image, setup the VM with multiple readers/init code.
func ExampleInstance_Run() {
imageFile := "testdata/retroImage"
img, err := vm.Load(imageFile, 50000)
if err != nil {
panic(err)
}

// output capture buffer
output := bytes.NewBuffer(nil)

// Setup the VM instance with os.Stdin as first reader, and we push another
// reader with some custom init code that will include and run the retro core tests.
i, err := vm.New(img, imageFile,
vm.Input(os.Stdin),
vm.Input(strings.NewReader("\"testdata/core.rx\" :include\n")),
vm.Output(output, false))

// run it
if err == nil {
err = i.Run()
}
if err != nil {
// in interactive use, err may be io.EOF if any of the IO channels gets closed
// in which case this would be a normal exit condition
panic(err)
}

// filter output to get the retro core test results.
b := bytes.Split(output.Bytes(), []byte{'\n'})
fmt.Printf("%s\n", b[len(b)-5])
fmt.Printf("%s\n", b[len(b)-4])

// Output:
// 360 tests run: 360 passed, 0 failed.
// 186 words checked, 0 words unchecked, 37 i/o words ignored.
}

// Shows how to setup a port handler.
func ExampleOutHandler() {
imageFile := "testdata/retroImage"
img, err := vm.Load(imageFile, 0)
if err != nil {
panic(err)
}

// we will use a buffered stdout
output := bufio.NewWriter(os.Stdout)
// so according to the spec, we should flush the output as soon as port 3
// is written to:
outputHandler := func(v vm.Cell) (vm.Cell, error) {
output.Flush()
return 0, nil
}

i, err := vm.New(img, imageFile,
vm.Input(strings.NewReader("6 7 * putn\n")),
vm.Output(output, false),
vm.OutHandler(3, outputHandler))
if err != nil {
panic(err)
}

if err = i.Run(); err != nil && err != io.EOF {
fmt.Fprintf(os.Stderr, "%+v\n", err)
}
// Retro 11.7.1
//
// ok 6
// ok 7
// ok *
// ok putn 42
// ok
}
15 changes: 7 additions & 8 deletions vm/image.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,9 @@ package vm

import (
"encoding/binary"
"fmt"
"os"
"unsafe"

"github.com/pkg/errors"
)

// Image encapsulates a VM's memory
Expand All @@ -32,16 +31,16 @@ type Image []Cell
func Load(fileName string, minSize int) (Image, error) {
f, err := os.Open(fileName)
if err != nil {
return nil, errors.Wrap(err, "Load")
return nil, err
}
defer f.Close()
st, err := f.Stat()
if err != nil {
return nil, errors.Wrap(err, "Load")
return nil, err
}
sz := st.Size()
if sz > int64((^uint(0))>>1) { // MaxInt
return nil, errors.Errorf("Load %v: file too large", fileName)
return nil, fmt.Errorf("Load %v: file too large", fileName)
}
var t Cell
sz /= int64(unsafe.Sizeof(t))
Expand All @@ -54,7 +53,7 @@ func Load(fileName string, minSize int) (Image, error) {
i := make(Image, sz)
err = binary.Read(f, binary.LittleEndian, i[:fileCells])
if err != nil {
return nil, errors.Wrap(err, "Load")
return nil, err
}
return i, nil
}
Expand All @@ -64,14 +63,14 @@ func Load(fileName string, minSize int) (Image, error) {
func (i Image) Save(fileName string, shrink bool) error {
f, err := os.OpenFile(fileName, os.O_WRONLY|os.O_CREATE, 0666)
if err != nil {
return errors.Wrap(err, "Save image")
return err
}
defer f.Close()

if shrink {
i = i[0:i[3]]
}
return errors.Wrap(binary.Write(f, binary.LittleEndian, i), "Save image")
return binary.Write(f, binary.LittleEndian, i)
}

// DecodeString returns the 0 terminated string starting at position pos in the image.
Expand Down
8 changes: 3 additions & 5 deletions vm/io.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@ import (
"time"
"unicode/utf8"
"unsafe"

"github.com/pkg/errors"
)

// readWriter wraps the WriteRune method. Works the same ad bufio.Writer.WriteRune.
Expand Down Expand Up @@ -188,7 +186,7 @@ func (i *Instance) ioWait() error {
} else {
i.out(utf8.RuneError, 1)
if err != nil {
return errors.Wrap(err, "ioWait input")
return err
}
}
case nil:
Expand All @@ -212,7 +210,7 @@ func (i *Instance) ioWait() error {
}
}
if err != nil {
return errors.Wrap(err, "ioWait output")
return err
}
}
i.out(0, 2)
Expand Down Expand Up @@ -247,7 +245,7 @@ func (i *Instance) ioWait() error {
var f *os.File
f, err = os.Open(i.Image.DecodeString(int(i.Pop())))
if err != nil {
return errors.Wrap(err, "Include failed")
return err
}
i.PushInput(f)
default:
Expand Down
2 changes: 1 addition & 1 deletion vm/vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import (
type Cell int32

const (
portCount = 64
portCount = 1024
dataSize = 1024
addressSize = 1024
)
Expand Down
100 changes: 18 additions & 82 deletions vm/vm_test.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,22 @@
// This file is part of ngaro - https://github.com/db47h/ngaro
//
// Copyright 2016 Denis Bernard <db047h@gmail.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package vm_test

import (
"bufio"
"bytes"
"fmt"
"io"
"os"
Expand All @@ -13,7 +25,6 @@ import (
"time"

"github.com/db47h/ngaro/vm"
"github.com/pkg/errors"
)

type C []vm.Cell
Expand Down Expand Up @@ -44,7 +55,7 @@ func check(t *testing.T, i *vm.Instance, ip int, stack C, rstack C) {
ip = len(i.Image)
}
if ip != i.PC {
t.Errorf("%+v", errors.Errorf("Bad IP %d != %d", i.PC, ip))
t.Errorf("%v", fmt.Errorf("Bad IP %d != %d", i.PC, ip))
}
stk := i.Data()
diff := len(stk) != len(stack)
Expand All @@ -57,7 +68,7 @@ func check(t *testing.T, i *vm.Instance, ip int, stack C, rstack C) {
}
}
if diff {
t.Errorf("%+v", errors.Errorf("Stack error: expected %d, got %d", stack, stk))
t.Errorf("%v", fmt.Errorf("Stack error: expected %d, got %d", stack, stk))
}
stk = i.Address()
diff = len(stk) != len(rstack)
Expand All @@ -70,7 +81,7 @@ func check(t *testing.T, i *vm.Instance, ip int, stack C, rstack C) {
}
}
if diff {
t.Errorf("%+v", errors.Errorf("Return stack error: expected %d, got %d", rstack, stk))
t.Errorf("%v", fmt.Errorf("Return stack error: expected %d, got %d", rstack, stk))
}
}

Expand Down Expand Up @@ -118,81 +129,6 @@ func TestLoop(t *testing.T) {

// TODO: make more...

// Shows how to load an image, setup the VM with multiple readers/init code.
func ExampleInstance_Run() {
imageFile := "testdata/retroImage"
img, err := vm.Load(imageFile, 50000)
if err != nil {
panic(err)
}

// output capture buffer
output := bytes.NewBuffer(nil)

// Setup the VM instance with os.Stdin as first reader, and we push another
// reader with some custom init code that will include and run the retro core tests.
i, err := vm.New(img, imageFile,
vm.Input(os.Stdin),
vm.Input(strings.NewReader("\"testdata/core.rx\" :include\n")),
vm.Output(output, false))

// run it
if err == nil {
err = i.Run()
}
if err != nil {
// in interactive use, err may be io.EOF if any of the IO channels gets closed
// in which case this would be a normal exit condition
panic(err)
}

// filter output to get the retro core test results.
b := bytes.Split(output.Bytes(), []byte{'\n'})
fmt.Printf("%s\n", b[len(b)-5])
fmt.Printf("%s\n", b[len(b)-4])

// Output:
// 360 tests run: 360 passed, 0 failed.
// 186 words checked, 0 words unchecked, 37 i/o words ignored.
}

// Shows how to setup a port handler.
func ExampleOutHandler() {
imageFile := "testdata/retroImage"
img, err := vm.Load(imageFile, 0)
if err != nil {
panic(err)
}

// we will use a buffered stdout
output := bufio.NewWriter(os.Stdout)
// so according to the spec, we should flush the output as soon as port 3
// is written to:
outputHandler := func(v vm.Cell) (vm.Cell, error) {
output.Flush()
return 0, nil
}

i, err := vm.New(img, imageFile,
vm.Input(strings.NewReader("6 7 * putn\n")),
vm.Output(output, false),
vm.OutHandler(3, outputHandler))
if err != nil {
panic(err)
}

if err = i.Run(); err != nil && errors.Cause(err) != io.EOF {
fmt.Fprintf(os.Stderr, "%+v\n", err)
}
// Retro 11.7.1
//
// ok 6
// ok 7
// ok *
// ok putn 42
// ok
}

var fib = []vm.Opcode{
vm.OpPush,
vm.OpLit, 0,
Expand Down Expand Up @@ -350,7 +286,7 @@ func BenchmarkRun(b *testing.B) {

fmt.Printf("Executed %d instructions in %.3fs. Perf: %.2f MIPS\n", c, el, float64(c)/1e6/el)
if err != nil {
switch errors.Cause(err) {
switch err {
case io.EOF: // stdin or stdout closed
default:
b.Errorf("%+v\n", err)
Expand Down

0 comments on commit 6491b8c

Please sign in to comment.