-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.py
153 lines (106 loc) · 3.96 KB
/
main.py
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
import argparse
import pathlib
import yaml
from datetime import datetime
from jinja2 import Environment, FunctionLoader, Template, select_autoescape
class Indent:
def __init__(self):
self.step_size = 4
self.value = 0
def increase(self):
self.value += 1
def decrease(self):
self.value -= 1
def reset(self):
self.value = 0
def as_string(self, whitespace=" "):
return whitespace * (self.step_size * self.value)
def load_template_file_contents(id: str) -> str:
with open(pathlib.Path("templates") / id) as f:
return f.read()
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("input", type=str, help="Opcode definition file path")
parser.add_argument("template", type=str, help="Template name")
parser.add_argument("--output", dest="output", type=str, help="Output file path")
args = parser.parse_args()
with open(args.input, 'r') as f:
opcode_list = yaml.load(f)
opcode_list = opcode_list['mnemonics']
template_environment_variables = {
"generated_at": datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S") + " UTC"
}
def render_c_lines(items, prefix="") -> str:
indent = Indent()
indent.increase()
lines = []
def format_name(name):
return prefix + str.upper(name).replace('.', '_')
def render_item(name, code):
return indent.as_string() + format_name(name) + " = " + code
for i in items:
if type(i['name']) == type(list()):
primary_name = i['name'][0]
for n in i['name']:
string_to_append = render_item(n, i["code"])
if n != primary_name:
string_to_append += " // alias for " + format_name(primary_name)
lines.append(string_to_append)
else:
lines.append(render_item(i["name"], i["code"]))
lines = str.join(',\n', lines)
return lines
def render_c_template(template: Template) -> str:
lines = render_c_lines(opcode_list, "OPCODE_")
template_variables = {
"environment": template_environment_variables,
"name": "_GeneratedOpCodes",
"lines": lines,
}
return template.render(**template_variables)
def render_cpp_template(template: Template) -> str:
lines = render_c_lines(opcode_list, "OPCODE_")
template_variables = {
"environment": template_environment_variables,
"name": "_GeneratedOpCodes",
"lines": lines,
}
return template.render(**template_variables)
def render_rust_template(template: Template) -> str:
lines = render_c_lines(opcode_list)
template_variables = {
"environment": template_environment_variables,
"name": "Opcodes",
"lines": lines,
}
return template.render(**template_variables)
template_map = {
"c": {
"template": "c-header.template",
"renderer": render_c_template,
},
"cpp": {
"template": "cpp-header.template",
"renderer": render_cpp_template,
},
"rust": {
"template": "rust.template",
"renderer": render_rust_template,
}
}
jinja_environment = Environment(
loader=FunctionLoader(load_template_file_contents),
autoescape=select_autoescape(),
keep_trailing_newline=True
)
requested_template = args.template
template_descriptor = template_map[requested_template]
jinja_template = jinja_environment.get_template(template_descriptor["template"])
result = template_descriptor["renderer"](jinja_template)
if args.output:
output_file_path = pathlib.Path(args.output)
with open(output_file_path, 'w+') as f:
f.write(result)
else:
print(result)
exit(0)