Move panics to errors

This commit is contained in:
Chris Sexton 2019-10-20 07:46:17 -04:00
parent 3f83afe287
commit e7a1e23dde
2 changed files with 44 additions and 16 deletions

View File

@ -9,14 +9,26 @@ import (
) )
const ( const (
MEM_MAX = 3000000
MEM_STD = 30000 MEM_STD = 30000
) )
type ErrMemoryOverflow struct {}
func (e ErrMemoryOverflow) Error() string { return "Memory Overflow" }
type ErrMemoryUnderflow struct {}
func (e ErrMemoryUnderflow) Error() string { return "Memory Underflow" }
type ErrInstructionLimit struct {}
func (e ErrInstructionLimit) Error() string { return "Instruction Limit Reached" }
type Machine struct { type Machine struct {
array []byte array []byte
ptr int ptr int
reader *bufio.Reader reader *bufio.Reader
// InstructionLimit prevents a runaway execution if running under a controlled environment
InstructionLimit int
// MemMax is the limit of how large memory can expand
MemMax int
} }
// Returns a new machine with standard memory size // Returns a new machine with standard memory size
@ -30,33 +42,34 @@ func New(in io.Reader) *Machine {
array: bytes, array: bytes,
ptr: 0, ptr: 0,
reader: bufio.NewReader(in), reader: bufio.NewReader(in),
InstructionLimit: 0,
MemMax: 3000000,
} }
} }
// Implements '>' // Implements '>'
func (m *Machine) PtrIncr() { func (m *Machine) PtrIncr() error {
if m.ptr >= len(m.array)-1 { if m.ptr >= len(m.array)-1 {
m.array = append(m.array, 0) m.array = append(m.array, 0)
} }
m.ptr += 1 m.ptr += 1
if m.ptr > MEM_MAX { if m.ptr > m.MemMax {
panic("Memory overflow") return ErrMemoryOverflow{}
} }
return nil
} }
// Implements '<' // Implements '<'
func (m *Machine) PtrDecr() { func (m *Machine) PtrDecr() error {
if m.ptr == 0 { if m.ptr == 0 {
panic("Memory underflow") return ErrMemoryUnderflow{}
} }
m.ptr -= 1 m.ptr -= 1
return nil
} }
// Implements '+' // Implements '+'
func (m *Machine) ByteIncr() { func (m *Machine) ByteIncr() {
if m.ptr > len(m.array)-1 {
fmt.Printf("Memory overflow, ptr=%d\n", m.ptr)
}
m.array[m.ptr] += 1 m.array[m.ptr] += 1
} }
@ -85,9 +98,13 @@ func (m *Machine) value() byte {
} }
// Run the whole program specified by input // Run the whole program specified by input
func (m *Machine) Run(input []byte) { func (m *Machine) Run(input []byte) error {
// execute the program instrCount := 0
for ip := 0; ip < len(input); ip++ { for ip := 0; ip < len(input); ip++ {
instrCount++
if m.InstructionLimit > 0 && instrCount > m.InstructionLimit {
return ErrInstructionLimit{}
}
instr := input[ip] instr := input[ip]
// if *ptr == 0, jump to ] // if *ptr == 0, jump to ]
if instr == '[' && m.value() == 0 { if instr == '[' && m.value() == 0 {
@ -110,9 +127,13 @@ func (m *Machine) Run(input []byte) {
} }
} }
} else if instr == '>' { } else if instr == '>' {
m.PtrIncr() if err := m.PtrIncr(); err != nil {
return err
}
} else if instr == '<' { } else if instr == '<' {
m.PtrDecr() if err := m.PtrDecr(); err != nil {
return err
}
} else if instr == '+' { } else if instr == '+' {
m.ByteIncr() m.ByteIncr()
} else if instr == '-' { } else if instr == '-' {
@ -124,4 +145,6 @@ func (m *Machine) Run(input []byte) {
} }
} }
return nil
} }

View File

@ -2,6 +2,7 @@ package main
import ( import (
"bufio" "bufio"
"fmt"
"io/ioutil" "io/ioutil"
"os" "os"
@ -14,15 +15,19 @@ func main() {
// read in the instructions // read in the instructions
if len(os.Args) < 2 { if len(os.Args) < 2 {
panic("No input given") fmt.Printf("No input given")
return
} }
file, err := os.Open(os.Args[1]) file, err := os.Open(os.Args[1])
reader := bufio.NewReader(file) reader := bufio.NewReader(file)
instructions, err = ioutil.ReadAll(reader) instructions, err = ioutil.ReadAll(reader)
if err != nil { if err != nil {
panic(err) fmt.Printf("Error: %s\n", err)
return
} }
m.Run(instructions) if err := m.Run(instructions); err != nil {
fmt.Printf("Error: %s\n", err)
}
} }