diff --git a/elm.go b/elm.go index a3dd973..08ae766 100644 --- a/elm.go +++ b/elm.go @@ -1,7 +1,94 @@ package main -import "fmt" +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() { - fmt.Println("Hello, World!") + 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() }