Implemented call instruction and function registering

This commit is contained in:
Sasha Koshka 2022-08-28 17:31:06 -04:00
parent 4067027588
commit ebf58c9427
1 changed files with 65 additions and 5 deletions

View File

@ -1,11 +1,43 @@
package creature
// Machine is a stack machine. It contains an array of integers as its program
// data, and provides methods to run this program data, as well as interact with
// it.
type Machine struct {
Program []int
stack []int
block []int
counter int
pointer int
// Program is not modified by the machine, and can be freely set before
// the machine is started.
Program []int
stack []int
block []int
counter int
pointer int
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)
// Error is an error type that can be returned from the machine's methods if
// they experience problems.
type Error int
const (
// ErrorIDTaken is returned by Register when a new function is
// registered with the same ID as another one.
ErrorIDTaken Error = iota
)
// Error returns a textual description of the error.
func (err Error) Error () (description string) {
switch err {
case ErrorIDTaken:
description = "this ID is taken by another function"
}
return
}
// Execute starts execution at the address specified by offset. The machine will
@ -112,6 +144,16 @@ func (machine *Machine) Execute (offset int) {
}
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 }
function, exists := machine.functions[id]
if exists {
function(machine)
}
}
machine.counter ++
}
@ -171,5 +213,23 @@ 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) {
if machine.functions == nil {
machine.functions = make(map[int] MachineFunction)
}
_, exists := machine.functions[id]
if exists {
err = ErrorIDTaken
return
}
machine.functions[id] = function
return
}
// Milk milks the stack machine
func (machine *Machine) Milk () {}