package main import ( "fmt" "os" "errors" ) const STACK_SIZE = 1024 type Operation int const ( HALT Operation = 0 PUSH Operation = 1 ADD Operation = 2 ) type Instruction struct { Operation Operation Operand int } type Machine struct { program []Instruction stack []int ip int sp int isHalted bool; } func Constructor() *Machine { m := Machine{} m.program = make([]Instruction, 0) m.stack = make([]int, STACK_SIZE) m.ip = 0 m.sp = 0 m.isHalted = false return &m } func (m* Machine) Push(i Instruction) error { m.program = append(m.program, i) return nil } func (m* Machine) Execute() error { instr := m.program[m.ip] switch op := instr.Operation; op { case HALT: m.isHalted = true; case PUSH: m.stack[m.sp] = instr.Operand m.sp++; m.ip++; case ADD: if (len(m.stack) < 2) { return errors.New("Stack size is less than required to execute ADD") } m.sp--; first := m.stack[m.sp] m.stack[m.sp] = 0; m.stack[m.sp - 1] = first + m.stack[m.sp - 1]; m.ip++; } return nil } func (m* Machine) Print() { fmt.Println("Stack:"); for i := 0; i <= m.sp; i++ { fmt.Println(m.stack[i]) } } func main() { m := Constructor() m.Push(Instruction{Operation: PUSH, Operand: 1}) m.Push(Instruction{Operation: PUSH, Operand: 2}) m.Push(Instruction{Operation: ADD}) m.Push(Instruction{Operation: HALT}) for !m.isHalted { m.Print() err := m.Execute() if err != nil { fmt.Fprintf(os.Stderr, "[ERR] %s", err); } } m.Print() }