Introduce jumps

This commit is contained in:
2024-01-20 04:29:33 +07:00
parent 435f203abe
commit bbf055b7c7

116
elm.go
View File

@@ -13,10 +13,15 @@ type Operation int
const ( const (
HALT Operation = 0 HALT Operation = 0
PUSH Operation = 1 PUSH Operation = 1
ADD Operation = 2 POP Operation = 2
SUB Operation = 3 DUP Operation = 3
MUL Operation = 4 ADD Operation = 4
DIV Operation = 5 SUB Operation = 5
MUL Operation = 6
DIV Operation = 7
EQ Operation = 8
JMP Operation = 9
JMPIF Operation = 10
) )
type Inst struct { type Inst struct {
@@ -61,33 +66,55 @@ func (m* Machine) Execute() error {
m.stack[m.sp] = instr.Operand m.stack[m.sp] = instr.Operand
m.sp++ m.sp++
m.ip++ 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: case ADD:
if (len(m.stack) < 2) { if (m.sp < 2) {
return errors.New("Stack size is less than required to execute ADD") return errors.New("Stack size is less than required to execute binary operation")
} }
m.stack[m.sp - 2] += m.stack[m.sp - 1]; m.stack[m.sp - 2] += m.stack[m.sp - 1];
m.sp-- m.sp--
m.ip++ m.ip++
case SUB: case SUB:
if (len(m.stack) < 2) { if (m.sp < 2) {
return errors.New("Stack size is less than required to execute SUB") return errors.New("Stack size is less than required to execute binary operation")
} }
m.stack[m.sp - 2] -= m.stack[m.sp - 1]; m.stack[m.sp - 2] -= m.stack[m.sp - 1];
m.sp-- m.sp--
m.ip++ m.ip++
case MUL: case MUL:
if (len(m.stack) < 2) { if (m.sp < 2) {
return errors.New("Stack size is less than required to execute MUL") return errors.New("Stack size is less than required to execute binary operation")
} }
m.stack[m.sp - 2] *= m.stack[m.sp - 1]; m.stack[m.sp - 2] *= m.stack[m.sp - 1];
m.sp-- m.sp--
m.ip++ m.ip++
case DIV: case DIV:
if (len(m.stack) < 2) { if (m.sp < 2) {
return errors.New("Stack size is less than required to execute DIV") 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) { 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.stack[m.sp - 2] /= m.stack[m.sp - 1];
m.sp-- m.sp--
m.ip++ 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 return nil
} }
@@ -111,22 +173,32 @@ func (m* Machine) Print() {
func main() { func main() {
m := Constructor() 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: 0})
m.Push(Inst{Operation: PUSH, Operand: 1}) m.Push(Inst{Operation: PUSH, Operand: 1})
m.Push(Inst{Operation: PUSH, Operand: 2})
m.Push(Inst{Operation: ADD}) m.Push(Inst{Operation: ADD})
m.Push(Inst{Operation: PUSH, Operand: 2}) m.Push(Inst{Operation: JMP, Operand: 1})
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: HALT})
for !m.isHalted { stackCounter := 0
for !m.isHalted && stackCounter < 69 {
m.Print() m.Print()
err := m.Execute() err := m.Execute()
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "[ERR] %s", err); fmt.Fprintf(os.Stderr, "[ERR] %s\n", err);
} os.Exit(1)
}
stackCounter++
} }
} }