lmc/main.go

78 lines
1.5 KiB
Go
Raw Normal View History

2016-07-10 14:35:33 +02:00
package main
import (
2016-10-20 01:58:16 +02:00
"errors"
2016-07-10 14:35:33 +02:00
"fmt"
"os"
2016-07-10 14:35:33 +02:00
)
2016-10-20 01:58:16 +02:00
func run(code []int16) error {
if len(code) != 100 {
return errors.New("Code must be exactly 100 mailboxes long")
}
// 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]
arg := i % 100
pc++
switch i - arg {
case IHALT:
return nil
case IADD:
accumulator += code[arg]
case ISUBTRACT:
accumulator -= code[arg]
case ISTORE:
code[arg] = accumulator
case ILOAD:
accumulator = code[arg]
case IBRANCH:
pc = int(i % 100)
case IBRANCH_IF_ZERO:
if accumulator == 0 {
pc = int(arg)
}
case IBRANCH_IF_POSITIVE:
if accumulator > 0 {
pc = int(arg)
}
case IIO:
switch arg {
case IO_INPUT:
fmt.Printf("Input: ")
fmt.Scanf("%d\n", &accumulator)
case IO_OUTPUT:
fmt.Printf("Output: %d\n", accumulator)
}
default:
e := fmt.Sprintf("Unsupported instruction %d at %d", i, pc)
return errors.New(e)
}
}
return errors.New("Program counter ran away")
}
2016-07-10 14:35:33 +02:00
func main() {
2016-10-20 00:12:24 +02:00
if len(os.Args) != 2 {
2016-10-20 01:47:07 +02:00
fmt.Printf("usage: %s file\n", os.Args[0])
} else if file, err := os.Open(os.Args[1]); err != nil {
fmt.Printf("Cannot open file: %s\n", err)
} else if code, err := Assemble(file); err != nil {
fmt.Printf("Assembly failed: %s\n", err)
2016-10-20 01:58:16 +02:00
} else if err = run(code); err != nil {
2016-10-20 01:47:07 +02:00
fmt.Printf("Runtime error: %s\n", err)
} else {
os.Exit(0)
2016-10-20 00:12:24 +02:00
}
2016-10-20 01:47:07 +02:00
os.Exit(1)
2016-07-10 14:35:33 +02:00
}