2f4a9de1b55e6ae734a2286a5d92148f38f47c51
[fur] / c_generation.py
1 import os
2
3 import jinja2
4
5 import crossplatform_ir_generation
6
7 TEMPLATE_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'templates')
8
9 def separate_labels_and_instructions(entry_list):
10     labels_to_instruction_indices = {}
11     instruction_list = []
12
13     for entry in entry_list:
14         if isinstance(entry, crossplatform_ir_generation.CIRInstruction):
15             instruction_list.append(entry)
16         elif isinstance(entry, crossplatform_ir_generation.CIRLabel):
17             labels_to_instruction_indices[entry.label] = len(instruction_list)
18
19     return labels_to_instruction_indices, tuple(instruction_list)
20
21 def generate_integer_argument(argument):
22     assert isinstance(argument, int)
23     return '(int32_t){}'.format(argument)
24
25 def generate_null_argument(argument):
26     assert argument is None
27     return 'NULL'
28
29 def generate_size_t_argument(argument):
30     assert isinstance(argument, int)
31     return '(size_t){}'.format(argument)
32
33 def generate_string_argument(argument):
34     return argument
35
36 def generate_symbol_argument(argument):
37     assert argument.startswith('sym(') and argument.endswith(')')
38     return '"{}"'.format(argument[4:-1])
39
40 def generate_argument(instruction):
41     try:
42         return {
43             'add': generate_size_t_argument,
44             'drop': generate_null_argument,
45             'end': generate_null_argument,
46             'call': generate_size_t_argument,
47             'idiv': generate_size_t_argument,
48             'mod': generate_size_t_argument,
49             'mul': generate_size_t_argument,
50             'pop': generate_symbol_argument,
51             'push': generate_symbol_argument,
52             'push_integer': generate_integer_argument,
53             'push_string': generate_string_argument,
54             'sub': generate_size_t_argument,
55         }[instruction.instruction](instruction.argument)
56
57     except KeyError:
58         import ipdb; ipdb.set_trace()
59
60 def generate(ir):
61     environment = jinja2.Environment(loader=jinja2.FileSystemLoader(TEMPLATE_PATH))
62     template = environment.get_template('program2.c')
63
64     labels_to_instruction_indices, instruction_list = separate_labels_and_instructions(
65         ir.entry_list,
66     )
67
68     return template.render(
69         labels_to_instruction_indices=labels_to_instruction_indices,
70         instruction_list=instruction_list,
71         generate_argument=generate_argument,
72     )