diff --git a/creature.go b/creature.go index 042c726..6dcf1c1 100644 --- a/creature.go +++ b/creature.go @@ -6,19 +6,19 @@ package creature type Machine struct { // Program is not modified by the machine, and can be freely set before // the machine is started. - Program []int - + Program []int + stack []int block []int counter int pointer int - functions map[int] MachineFunction + functions map[int]MachineFunction } // MachineFunction is a function that can extend the functionality of the stack // machine. It is passed a pointer to the machine that is calling it, and the // machine will halt execution if true is returned. -type MachineFunction func (machine *Machine) (stop bool) +type MachineFunction func(machine *Machine) (stop bool) // Error is an error type that can be returned from the machine's methods if // they experience problems. @@ -31,7 +31,7 @@ const ( ) // Error returns a textual description of the error. -func (err Error) Error () (description string) { +func (err Error) Error() (description string) { switch err { case ErrorIDTaken: description = "this ID is taken by another function" @@ -42,15 +42,15 @@ func (err Error) Error () (description string) { // Reset resets the stack of the machine. This should be called before Execute, // since Execute does not reset the stack. -func (machine *Machine) Reset () { - machine.stack = nil +func (machine *Machine) Reset() { + machine.stack = nil machine.pointer = 0 } // Execute starts execution at the address specified by offset. The machine will // run until a HALT instruction is encountered, or the end of program memory is // reached. -func (machine *Machine) Execute (offset int) { +func (machine *Machine) Execute(offset int) { machine.counter = offset for machine.counter < len(machine.Program) { @@ -58,88 +58,96 @@ func (machine *Machine) Execute (offset int) { case 0x0: // PUSH // push the next word in program memory onto the stack - machine.counter ++ + machine.counter++ machine.Push(machine.instruction()) - + case 0x1: // POP // pop the top word off of the stack, and discard it machine.Pop() - + case 0x2: // LOAD // push the word at an address onto the stack machine.Push(machine.Peek(machine.Pop())) - + case 0x3: // STOR // store a word at an address machine.Poke(machine.Pop(), machine.Pop()) - + case 0x4: // ADD // adds the last two words on the stack machine.Push(machine.Pop() + machine.Pop()) - + case 0x5: // SUB // subtracts the second to last word on the stack from // the last word on the stack machine.Push(machine.Pop() - machine.Pop()) - + case 0x6: // MUL // multiplies the last two words on the stack machine.Push(machine.Pop() * machine.Pop()) - + case 0x7: // DIV // divides the last word on the stack by the second to // last word on the stack machine.Push(machine.Pop() / machine.Pop()) - + case 0x8: // EQ // checks if the last two words on the stack are equal equal := 0 - if machine.Pop() == machine.Pop() { equal = 1 } + if machine.Pop() == machine.Pop() { + equal = 1 + } machine.Push(equal) - + case 0x9: // GT // checks if the last word on the stack is greater than // the second to last word on the stack greater := 0 - if machine.Pop() > machine.Pop() { greater = 1 } + if machine.Pop() > machine.Pop() { + greater = 1 + } machine.Push(greater) - + case 0xa: // LT // checks if the last word on the stack is less than the // second to last word on the stack less := 0 - if machine.Pop() > machine.Pop() { less = 1 } + if machine.Pop() > machine.Pop() { + less = 1 + } machine.Push(less) - + case 0xb: // NEQ // checks if the last two words on the stack are not // equal notEqual := 0 - if machine.Pop() != machine.Pop() { notEqual = 1 } + if machine.Pop() != machine.Pop() { + notEqual = 1 + } machine.Push(notEqual) - + case 0xc: // MOD // performs a modulo operation of the second to last // word on the stack to the last word on the stack machine.Push(machine.Pop() % machine.Pop()) - + case 0xd: // HALT // stops execution return - + case 0xe: // JMP // jump to the address specified by the last word on the @@ -149,25 +157,27 @@ func (machine *Machine) Execute (offset int) { if machine.Pop() != 0 { machine.counter = jumpTo - 1 } - + case 0xf: // CAL // call an implementation-defined subroutine, with the // id specified by the last word on the stack. this may // push and pop various things from the stack id := machine.Pop() - if machine.functions == nil { break } + if machine.functions == nil { + break + } function, exists := machine.functions[id] if exists { function(machine) } } - machine.counter ++ + machine.counter++ } } // Instruction returns the current instruction in program memory. -func (machine *Machine) instruction () (instruction int) { +func (machine *Machine) instruction() (instruction int) { instruction = machine.Program[machine.counter] return } @@ -175,16 +185,16 @@ func (machine *Machine) instruction () (instruction int) { // reallocateStack changes the size of the stack to something reasonable. This // should be called then the stack pointer is really small compared to the // actual stack size, or the stack pointer is bigger than the stack. -func (machine *Machine) reallocateStack () { - reallocatedStack := make([]int, machine.pointer * 3 / 2) +func (machine *Machine) reallocateStack() { + reallocatedStack := make([]int, machine.pointer*3/2) copy(reallocatedStack, machine.stack) machine.stack = reallocatedStack } // Push pushes a word onto the stack, increasing the stack pointer and // reallocating the stack if necessary. -func (machine *Machine) Push (word int) { - machine.pointer ++ +func (machine *Machine) Push(word int) { + machine.pointer++ if len(machine.stack) <= machine.pointer { machine.reallocateStack() } @@ -192,29 +202,29 @@ func (machine *Machine) Push (word int) { // Pop pops the last word off of the stack, and returns it, decreasing the stack // pointer and reallocating the stack if necessary. -func (machine *Machine) Pop () (word int) { +func (machine *Machine) Pop() (word int) { word = machine.stack[machine.pointer] - machine.pointer -- + machine.pointer-- - if machine.pointer < len(machine.stack) / 3 { + if machine.pointer < len(machine.stack)/3 { machine.reallocateStack() } - + return } -// Peek returns the word at address in the block -func (machine *Machine) Peek (address int) (word int) { +// Peek returns the word at address in the block. +func (machine *Machine) Peek(address int) (word int) { if address < len(machine.block) { word = machine.block[address] } return } -// Poke sets the value at address in the block to word -func (machine *Machine) Poke (address int, word int) { +// Poke sets the value at address in the block to word. +func (machine *Machine) Poke(address int, word int) { if address >= len(machine.block) { - reallocatedBlock := make([]int, address * 3 / 2) + reallocatedBlock := make([]int, address*3/2) copy(reallocatedBlock, machine.block) machine.block = reallocatedBlock } @@ -222,9 +232,9 @@ func (machine *Machine) Poke (address int, word int) { // Register registers a function at the specified ID. If there is already a // function registered at that ID, this method will return an error. -func (machine *Machine) Register (id int, function MachineFunction) (err error) { +func (machine *Machine) Register(id int, function MachineFunction) (err error) { if machine.functions == nil { - machine.functions = make(map[int] MachineFunction) + machine.functions = make(map[int]MachineFunction) } _, exists := machine.functions[id] @@ -239,16 +249,18 @@ func (machine *Machine) Register (id int, function MachineFunction) (err error) } // Unregister removes a function that is registered at the specified ID. -func (machine *Machine) Unregister (id int) { - if machine.functions == nil { return } +func (machine *Machine) Unregister(id int) { + if machine.functions == nil { + return + } delete(machine.functions, id) } // LoadMemory loads the contents of block into the machine's memory. -func (machine *Machine) LoadMemory (block []int) { +func (machine *Machine) LoadMemory(block []int) { machine.block = make([]int, len(block)) copy(machine.block, block) } -// Milk milks the stack machine -func (machine *Machine) Milk () {} +// Milk milks the stack machine. +func (machine *Machine) Milk() {}