-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathintcode.go
127 lines (113 loc) · 3.3 KB
/
intcode.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package main
import (
"flag"
"fmt"
"io/ioutil"
"os"
"runtime"
)
const version = "v9.3"
var (
executedProgramFilename string
executedProgramFile *os.File
outputFilename string
outputFile *os.File
inputFilename string
inputFile *os.File
showDebug bool
showStats bool
additionalMemory uint
)
func main() {
flags()
openFiles()
defer executedProgramFile.Close()
defer inputFile.Close()
programFilename := flag.Arg(0)
if programFilename == "" {
printInfo()
return
}
programFile, err := ioutil.ReadFile(programFilename)
if err != nil {
panic(err)
}
runProgram(string(programFile))
}
// runProgram creates a new program, executes it, prints the executed program and shows stats
func runProgram(str string) {
// Create a new program and execute it
p := New(str, additionalMemory)
p.InputReader = inputFile
p.Debug = showDebug
if showStats {
p.Stats = newStats()
}
p.Exec()
// Print executed program
if executedProgramFile != nil {
fmt.Fprintln(executedProgramFile, p.Ints.String())
}
// Show stats
if showStats {
fmt.Fprintln(os.Stderr, "Stats:")
fmt.Fprintln(os.Stderr, p.Stats.String())
}
}
// openFiles opens the executed program file, the output file and the input file
// specified by their filename variable.
func openFiles() {
// Open executed program file
if executedProgramFilename == "" {
executedProgramFile = nil
} else if executedProgramFilename == "-" {
executedProgramFile = os.Stdout
} else {
var err error
executedProgramFile, err = os.OpenFile(executedProgramFilename, os.O_CREATE|os.O_WRONLY, 0664)
if err != nil {
panic(err)
}
}
// Open output file
if outputFilename == "" {
outputFile = os.Stdout
} else {
var err error
outputFile, err = os.OpenFile(outputFilename, os.O_CREATE|os.O_WRONLY, 0664)
if err != nil {
panic(err)
}
}
// Open input file
if inputFilename == "" {
inputFile = os.Stdin
} else {
var err error
inputFile, err = os.Open(inputFilename)
if err != nil {
panic(err)
}
}
}
// flags parsed the program arguments into the variables.
func flags() {
flag.Usage = func() {
fmt.Fprintf(flag.CommandLine.Output(), "Usage: %s <flags> <filename>\n\n", os.Args[0])
fmt.Fprintln(flag.CommandLine.Output(), "Flags:")
flag.PrintDefaults()
}
flag.StringVar(&executedProgramFilename, "executed-program", "", "File to print the executed program to. Use '-' to print to console")
flag.StringVar(&inputFilename, "input", "", "File to read input values from")
flag.StringVar(&outputFilename, "output", "", "File to print output values to")
flag.BoolVar(&showDebug, "showDebug", false, "Trace program execution via showDebug output")
flag.BoolVar(&showStats, "stats", false, "Show statistics about execution duration and memory accesses")
flag.UintVar(&additionalMemory, "mem", 42, "Number of ints that are allocated for the memory in addition "+
"to the program. If a memory address outside the allocated memory is requested, the memory is increased by that offset")
flag.Parse()
}
// printInfo prints the version number and help for this intcode interpreter.
func printInfo() {
fmt.Printf("INTCODE Computer %s on %s %s/%s\n\n", version, runtime.Version(), runtime.GOARCH, runtime.GOOS)
fmt.Printf("Use \"%s -help\" for help\n", os.Args[0])
}