Introduce jumps
This commit is contained in:
120
elm.go
120
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++
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user