Skip to content

Commit abe3480

Browse files
committed
Complete code rewriting
1 parent a9ea893 commit abe3480

File tree

1 file changed

+102
-67
lines changed

1 file changed

+102
-67
lines changed

main.py

Lines changed: 102 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,9 @@
11
import argparse
2-
import typing
2+
import pathlib
33
import yaml
4-
from time import gmtime, strftime
54

6-
parser = argparse.ArgumentParser()
7-
parser.add_argument("input", type=str, help="OpCode definition file path")
8-
parser.add_argument("template", type=str, help="Template file path")
9-
parser.add_argument("output", type=str, help="Output file name")
10-
11-
args = parser.parse_args()
5+
from datetime import datetime
6+
from jinja2 import Environment, FunctionLoader, Template, select_autoescape
127

138

149
class Indent:
@@ -25,94 +20,134 @@ def decrease(self):
2520
def reset(self):
2621
self.value = 0
2722

28-
def generate_spaces(self):
29-
return " " * (self.step_size * self.value)
23+
def as_string(self, whitespace=" "):
24+
return whitespace * (self.step_size * self.value)
3025

3126

32-
class OpCodeCppListGenerator:
33-
def __init__(self):
34-
self.prefix = ''
35-
self.indent = Indent()
27+
def load_template_file_contents(id: str) -> str:
28+
with open(pathlib.Path("templates") / id) as f:
29+
return f.read()
30+
31+
32+
if __name__ == "__main__":
33+
parser = argparse.ArgumentParser()
34+
parser.add_argument("input", type=str, help="Opcode definition file path")
35+
parser.add_argument("template", type=str, help="Template name")
36+
parser.add_argument("--output", dest="output", type=str, help="Output file path")
37+
38+
args = parser.parse_args()
39+
40+
with open(args.input, 'r') as f:
41+
opcode_list = yaml.load(f)
42+
opcode_list = opcode_list['mnemonics']
43+
44+
template_environment_variables = {
45+
"generated_at": datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S") + " UTC"
46+
}
47+
3648

37-
def format_name(self, name):
38-
return str.upper(name).replace('.', '_')
49+
def render_c_lines(items, prefix="") -> str:
50+
indent = Indent()
51+
indent.increase()
3952

40-
def generate_key(self, name):
41-
return self.prefix + name
53+
lines = []
4254

43-
def generate_value(self, code):
44-
return code
55+
def format_name(name):
56+
return prefix + str.upper(name).replace('.', '_')
4557

46-
def prepare_items(self, items):
47-
result = []
58+
def render_item(name, code):
59+
return indent.as_string() + format_name(name) + " = " + code
4860

4961
for i in items:
5062
if type(i['name']) == type(list()):
5163
primary_name = i['name'][0]
5264

5365
for n in i['name']:
54-
string_to_append = self.indent.generate_spaces() + self.generate_key(self.format_name(n)) \
55-
+ " = " + self.generate_value(i['code'])
66+
string_to_append = render_item(n, i["code"])
5667

57-
if (n != primary_name):
58-
string_to_append += " /* alias for " + self.format_name(primary_name) + " */"
68+
if n != primary_name:
69+
string_to_append += " // alias for " + format_name(primary_name)
5970

60-
result.append(string_to_append)
71+
lines.append(string_to_append)
6172
else:
62-
result.append(self.indent.generate_spaces() + self.generate_key(self.format_name(i['name'])) + " = " + self.generate_value(i['code']))
73+
lines.append(render_item(i["name"], i["code"]))
6374

64-
return result
75+
lines = str.join(',\n', lines)
6576

66-
def generate_enumeration_lines(self, items):
67-
lines = self.prepare_items(items)
77+
return lines
6878

69-
# Do not use 'os.linesep' on Windows. It generates an extra line break
70-
return str.join(',\n', lines)
7179

80+
def render_c_template(template: Template) -> str:
81+
lines = render_c_lines(opcode_list, "OPCODE_")
7282

73-
current_time = strftime("%Y-%m-%d %H:%M:%S %z", gmtime())
83+
template_variables = {
84+
"environment": template_environment_variables,
85+
"name": "_GeneratedOpCodes",
86+
"lines": lines,
87+
}
7488

75-
# Read definition file
76-
input_file = open(args.input, 'r')
77-
opcode_list = yaml.load(input_file)
78-
opcode_list = opcode_list['mnemonics']
79-
input_file.close()
89+
return template.render(**template_variables)
8090

81-
# Read template
82-
template_file = open(args.template, mode='r')
83-
template_content = template_file.read()
84-
template_file.close()
8591

86-
output_file_name = args.output
92+
def render_cpp_template(template: Template) -> str:
93+
lines = render_c_lines(opcode_list, "OPCODE_")
8794

88-
if output_file_name is None:
89-
output_file_name = '/._opcodes.h'
95+
template_variables = {
96+
"environment": template_environment_variables,
97+
"name": "_GeneratedOpCodes",
98+
"lines": lines,
99+
}
90100

91-
opcodes_file_generator_settings = {
92-
"outputFileName": output_file_name,
93-
"fileTemplate": template_content,
94-
"name": "_GeneratedOpCodes",
95-
"prefix": "OPCODE_",
96-
}
101+
return template.render(**template_variables)
97102

98-
with open(opcodes_file_generator_settings["outputFileName"], 'w') as f:
99-
cpp_enumeration_generator = OpCodeCppListGenerator()
100-
cpp_enumeration_generator.prefix = opcodes_file_generator_settings["prefix"]
101103

102-
cpp_enumeration_generator.indent.increase()
103-
renderedItems = cpp_enumeration_generator.generate_enumeration_lines(
104-
opcode_list)
105-
cpp_enumeration_generator.indent.reset()
104+
def render_rust_template(template: Template) -> str:
105+
lines = render_c_lines(opcode_list)
106106

107-
result = opcodes_file_generator_settings["fileTemplate"]
107+
template_variables = {
108+
"environment": template_environment_variables,
109+
"name": "Opcodes",
110+
"lines": lines,
111+
}
108112

109-
parameters = {
110-
"${generated_at}": current_time,
111-
'${name}': opcodes_file_generator_settings["name"],
112-
'${items}': renderedItems
113+
return template.render(**template_variables)
114+
115+
116+
template_map = {
117+
"c": {
118+
"template": "c-header.template",
119+
"renderer": render_c_template,
120+
},
121+
"cpp": {
122+
"template": "cpp-header.template",
123+
"renderer": render_cpp_template,
124+
},
125+
"rust": {
126+
"template": "rust.template",
127+
"renderer": render_rust_template,
128+
}
113129
}
114130

115-
for k, v in parameters.items():
116-
result = result.replace(k, v)
131+
jinja_environment = Environment(
132+
loader=FunctionLoader(load_template_file_contents),
133+
autoescape=select_autoescape(),
134+
keep_trailing_newline=True
135+
)
136+
137+
requested_template = args.template
138+
139+
template_descriptor = template_map[requested_template]
140+
141+
jinja_template = jinja_environment.get_template(template_descriptor["template"])
142+
143+
result = template_descriptor["renderer"](jinja_template)
144+
145+
if args.output:
146+
output_file_path = pathlib.Path(args.output)
147+
148+
with open(output_file_path, 'w+') as f:
149+
f.write(result)
150+
else:
151+
print(result)
117152

118-
f.write(result)
153+
exit(0)

0 commit comments

Comments
 (0)