-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
executable file
·154 lines (145 loc) · 3.9 KB
/
main.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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
package main
import (
"bufio"
"fmt"
"os"
"github.com/BUAA-SE-Compiling/vm"
flag "github.com/spf13/pflag"
)
// Run runs the epf file.
func Run(file *os.File) {
epf, err := vm.NewEPFv1FromFile(file)
if err != nil {
panic(err)
}
vm := vm.NewVMDefault(len(epf.GetInstructions()), epf.GetEntry())
vm.Load(epf.GetInstructions())
if err := vm.Run(); err != nil {
fmt.Println(vm)
panic(err)
}
}
// Interprete interprets the input file directly.
func Interprete(file *os.File) {
scanner := bufio.NewScanner(file)
instructions := []vm.Instruction{}
linenum := 0
for scanner.Scan() {
linenum++
single := vm.ParseInstruction(scanner.Text())
if single == nil {
fmt.Fprintf(os.Stderr, "Line %v: Bad instruction", linenum)
}
instructions = append(instructions, *single)
}
vm := vm.NewVMDefault(len(instructions), 0)
vm.Load(instructions)
if err := vm.Run(); err != nil {
fmt.Println(vm)
panic(err)
}
}
// Decompile decompiles the epf file.
func Decompile(file *os.File) {
epf, err := vm.NewEPFv1FromFile(file)
if err != nil {
panic(err)
}
for _, i := range epf.GetInstructions() {
fmt.Println(i)
}
return
}
// Assemble assembles the text file to an epf file.
func Assemble(in *os.File, out *os.File) {
scanner := bufio.NewScanner(in)
instructions := []vm.Instruction{}
linenum := 0
for scanner.Scan() {
linenum++
single := vm.ParseInstruction(scanner.Text())
if single == nil {
fmt.Fprintf(os.Stderr, "Line %v: Bad instruction", linenum)
}
instructions = append(instructions, *single)
}
epf := vm.NewEPFv1FromInstructions(instructions, 0)
epf.WriteFile(out)
return
}
// We don't know whehter a flag is unset or set with an empty string if its default value is an empty string.
func isFlagPassed(name string) bool {
found := false
flag.Visit(func(f *flag.Flag) {
if f.Name == name {
found = true
}
})
return found
}
func main() {
var input string
var output string
var decompile bool
var run bool
var debug bool
var help bool
var assemble bool
var interprete bool
flag.CommandLine.Init("Default", flag.ContinueOnError)
flag.Usage = func() {
fmt.Fprintf(os.Stderr, "A vm implementation for mini plc0.\n")
fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
flag.PrintDefaults()
}
flag.StringVarP(&input, "input", "i", "-", "The input file. The default is os.Stdin.")
flag.StringVarP(&output, "output", "o", "", "The output file.")
flag.BoolVarP(&decompile, "decompile", "D", false, "Decompile without running.")
flag.BoolVarP(&run, "run", "R", false, "Run the file.")
flag.BoolVarP(&interprete, "interprete", "I", false, "Interprete the file.")
flag.BoolVarP(&debug, "debug", "d", false, "Debug the file.")
flag.BoolVarP(&help, "help", "h", false, "Show this message.")
flag.BoolVarP(&assemble, "assemble", "A", false, "Assemble a text file to an EPFv1 file.")
if err := flag.CommandLine.Parse(os.Args[1:]); err != nil {
fmt.Println(err)
fmt.Fprintf(os.Stderr, "Run with --help for details.\n")
os.Exit(2)
}
if help || (decompile && !isFlagPassed("output")) {
flag.Usage()
os.Exit(2)
}
if !debug && !run && !decompile && !assemble && !interprete {
fmt.Fprintf(os.Stderr, "You must choose to decomple, run, assemble, interprete or debug.\n")
fmt.Fprintf(os.Stderr, "Run with --help for details.\n")
os.Exit(2)
}
var file *os.File
var err error
if input != "-" {
file, err = os.Open(input)
if err != nil {
panic(err)
}
defer file.Close()
} else {
file = os.Stdin
}
if debug {
Debug(file)
} else if decompile {
Decompile(file)
} else if run {
Run(file)
} else if assemble {
out, err := os.OpenFile(output, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0660)
if err != nil {
panic(err)
}
defer out.Close()
Assemble(file, out)
} else if interprete {
Interprete(file)
}
os.Exit(0)
}