From bbf055b7c7b624bdf1a5df87f920502794a0eb02 Mon Sep 17 00:00:00 2001 From: HiveBeats Date: Sat, 20 Jan 2024 04:29:33 +0700 Subject: [PATCH] Introduce jumps --- elm.go | 120 +++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 96 insertions(+), 24 deletions(-) diff --git a/elm.go b/elm.go index f08101e..1306cb8 100644 --- a/elm.go +++ b/elm.go @@ -13,10 +13,15 @@ type Operation int const ( HALT Operation = 0 PUSH Operation = 1 - ADD Operation = 2 - SUB Operation = 3 - MUL Operation = 4 - DIV Operation = 5 + POP Operation = 2 + DUP Operation = 3 + ADD Operation = 4 + SUB Operation = 5 + MUL Operation = 6 + DIV Operation = 7 + EQ Operation = 8 + JMP Operation = 9 + JMPIF Operation = 10 ) type Inst struct { @@ -61,33 +66,55 @@ func (m* Machine) Execute() error { m.stack[m.sp] = instr.Operand m.sp++ m.ip++ + case POP: + if (m.sp <= 0) { + return errors.New("Empty Stack") + } + + m.stack[m.sp] = 0 + m.sp-- + case DUP: + if (m.sp - instr.Operand <= 0) { + return errors.New("Stack Underflow") + } + + if (m.sp >= STACK_SIZE) { + return errors.New("Stack Overflow"); + } + + if (instr.Operand < 0) { + return errors.New("Illegal access") + } + + m.stack[m.sp] = m.stack[m.sp - 1 - instr.Operand] + m.sp++ case ADD: - if (len(m.stack) < 2) { - return errors.New("Stack size is less than required to execute ADD") + if (m.sp < 2) { + return errors.New("Stack size is less than required to execute binary operation") } m.stack[m.sp - 2] += m.stack[m.sp - 1]; m.sp-- m.ip++ case SUB: - if (len(m.stack) < 2) { - return errors.New("Stack size is less than required to execute SUB") + if (m.sp < 2) { + return errors.New("Stack size is less than required to execute binary operation") } m.stack[m.sp - 2] -= m.stack[m.sp - 1]; m.sp-- m.ip++ case MUL: - if (len(m.stack) < 2) { - return errors.New("Stack size is less than required to execute MUL") + if (m.sp < 2) { + return errors.New("Stack size is less than required to execute binary operation") } m.stack[m.sp - 2] *= m.stack[m.sp - 1]; m.sp-- m.ip++ case DIV: - if (len(m.stack) < 2) { - return errors.New("Stack size is less than required to execute DIV") + if (m.sp < 2) { + return errors.New("Stack size is less than required to execute binary operation") } if (m.stack[m.sp - 2] == 0 || m.stack[m.sp - 1] == 0) { @@ -97,6 +124,41 @@ func (m* Machine) Execute() error { m.stack[m.sp - 2] /= m.stack[m.sp - 1]; m.sp-- m.ip++ + case EQ: + if (m.sp < 2) { + return errors.New("Stack size is less than required to execute binary operation") + } + + eq := m.stack[m.sp - 1] == m.stack[m.sp - 2] + if (eq) { + m.stack[m.sp - 2] = 1 + } else { + m.stack[m.sp - 2] = 0 + } + + m.sp-- + m.ip++ + case JMP: + if (m.ip < instr.Operand || instr.Operand < 0) { + return errors.New("Illegal access") + } + + m.ip = instr.Operand + case JMPIF: + if (m.sp < 1) { + return errors.New("Stack Underflow") + } + + if (m.ip < instr.Operand || instr.Operand < 0) { + return errors.New("Illegal access") + } + + if (m.stack[m.sp - 1] >= 1) { + m.sp-- + m.ip = instr.Operand + } else { + m.ip++ + } } return nil } @@ -111,22 +173,32 @@ func (m* Machine) Print() { func main() { m := Constructor() - m.Push(Inst{Operation: PUSH, Operand: 1}) - m.Push(Inst{Operation: PUSH, Operand: 2}) - m.Push(Inst{Operation: ADD}) - m.Push(Inst{Operation: PUSH, Operand: 2}) - m.Push(Inst{Operation: SUB}) - m.Push(Inst{Operation: PUSH, Operand: 6}) - m.Push(Inst{Operation: MUL}) - m.Push(Inst{Operation: PUSH, Operand: 2}) - m.Push(Inst{Operation: DIV}) - m.Push(Inst{Operation: HALT}) + // m.Push(Inst{Operation: PUSH, Operand: 1}) + // m.Push(Inst{Operation: PUSH, Operand: 2}) + // m.Push(Inst{Operation: ADD}) + // m.Push(Inst{Operation: PUSH, Operand: 2}) + // m.Push(Inst{Operation: SUB}) + // m.Push(Inst{Operation: PUSH, Operand: 6}) + // m.Push(Inst{Operation: MUL}) + // m.Push(Inst{Operation: PUSH, Operand: 2}) + // m.Push(Inst{Operation: DIV}) + // m.Push(Inst{Operation: HALT}) - for !m.isHalted { + m.Push(Inst{Operation: PUSH, Operand: 0}) + m.Push(Inst{Operation: PUSH, Operand: 1}) + m.Push(Inst{Operation: ADD}) + m.Push(Inst{Operation: JMP, Operand: 1}) + m.Push(Inst{Operation: HALT}) + + stackCounter := 0 + for !m.isHalted && stackCounter < 69 { m.Print() err := m.Execute() if err != nil { - fmt.Fprintf(os.Stderr, "[ERR] %s", err); + fmt.Fprintf(os.Stderr, "[ERR] %s\n", err); + os.Exit(1) } + stackCounter++ + } }