lmc/machine.go

62 lines
1.1 KiB
Go
Raw Normal View History

2016-07-10 14:35:33 +02:00
package main
2016-10-20 00:12:24 +02:00
import (
"errors"
"fmt"
)
2016-07-10 14:35:33 +02:00
2016-10-20 00:12:24 +02:00
func Run(code []int16) error {
if len(code) != 100 {
return errors.New("Code must be exactly 100 mailboxes long")
2016-07-10 14:35:33 +02:00
}
2016-10-20 00:12:24 +02:00
// for i, x := range code {
// fmt.Printf("%d: %d\n", i, x)
// }
// fmt.Println()
var accumulator int16 = 0
pc := 0
for pc >= 0 && pc < len(code) {
i := code[pc]
2016-10-20 01:31:15 +02:00
arg := i % 100
2016-10-20 00:12:24 +02:00
pc++
2016-10-20 01:31:15 +02:00
switch i - arg {
2016-10-20 00:12:24 +02:00
case IHALT:
return nil
case IADD:
2016-10-20 01:31:15 +02:00
accumulator += code[arg]
2016-10-20 00:12:24 +02:00
case ISUBTRACT:
2016-10-20 01:31:15 +02:00
accumulator -= code[arg]
2016-10-20 00:12:24 +02:00
case ISTORE:
2016-10-20 01:31:15 +02:00
code[arg] = accumulator
2016-10-20 00:12:24 +02:00
case ILOAD:
2016-10-20 01:31:15 +02:00
accumulator = code[arg]
2016-10-20 00:12:24 +02:00
case IBRANCH:
pc = int(i % 100)
case IBRANCH_IF_ZERO:
if accumulator == 0 {
2016-10-20 01:31:15 +02:00
pc = int(arg)
2016-10-20 00:12:24 +02:00
}
case IBRANCH_IF_POSITIVE:
if accumulator > 0 {
2016-10-20 01:31:15 +02:00
pc = int(arg)
2016-10-20 00:12:24 +02:00
}
2016-10-20 01:31:15 +02:00
case IIO:
switch arg {
case IO_INPUT:
2016-10-20 00:12:24 +02:00
fmt.Printf("Input: ")
fmt.Scanf("%d\n", &accumulator)
2016-10-20 01:31:15 +02:00
case IO_OUTPUT:
2016-10-20 00:12:24 +02:00
fmt.Printf("Output: %d\n", accumulator)
}
2016-10-20 01:31:15 +02:00
default:
e := fmt.Sprintf("Unsupported instruction %d at %d", i, pc)
return errors.New(e)
2016-10-20 00:12:24 +02:00
}
}
return errors.New("Program counter ran away")
2016-07-10 14:35:33 +02:00
}