summaryrefslogtreecommitdiff
path: root/lib/codegen.py
blob: b383f20d400371d88aa14e5f3356f6b3abd51304 (plain)
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
"""Code generators for multipass dummy drivers for online model evaluation."""

header_template = """
#ifndef DFATOOL_{name}_H
#define DFATOOL_{name}_H

class {name}
{{
private:
{name}(const {name} &copy);

public:
{enums}
{functions}
}};

extern {name} {name_lower};

#endif
"""

implementation_template = """
#include "driver/dummy.h"

{functions}

{name} {name_lower};
"""

class MultipassDriver:
    """Generate C++ header and no-op implementation for a multipass driver based on a DFA model."""

    def __init__(self, name, pta, class_info, enum = dict()):
        self.impl = ''
        self.header = ''
        self.name = name
        self.pta = pta
        self.class_info = class_info
        self.enum = enum

        function_definitions = list()
        function_bodies = list()

        function_definitions.append('{}() {{}}'.format(self.name))
        seen_transitions = set()

        for transition in self.pta.transitions:
            if transition.name in seen_transitions:
                continue
            seen_transitions.add(transition.name)

            # XXX right now we only verify whether both functions have the
            # same number of arguments. This breaks in many overloading cases.
            function_info = self.class_info.function[transition.name]
            for function_candidate in self.class_info.functions:
                if function_candidate.name == transition.name and len(function_candidate.argument_types) == len(transition.arguments):
                    function_info = function_candidate

            function_arguments = list()

            for i in range(len(transition.arguments)):
                function_arguments.append('{} {}'.format(function_info.argument_types[i], transition.arguments[i]))

            function_definition = '{} {}({})'.format(function_info.return_type, transition.name, ', '.join(function_arguments))
            function_head = '{} {}::{}({})'.format(function_info.return_type, self.name, transition.name, ', '.join(function_arguments))

            function_body = str()

            if function_info.return_type != 'void':
                function_body = 'return 0;\n'

            function_definitions.append(function_definition + ';')
            function_bodies.append('{} {{\n{}}}'.format(function_head, function_body))

        enums = list()
        for enum_name in self.enum.keys():
            enums.append('enum {} {{ {} }};'.format(enum_name, ', '.join(self.enum[enum_name])))

        self.header = header_template.format(name = self.name, name_lower = self.name.lower(), functions = '\n'.join(function_definitions), enums = '\n'.join(enums))
        self.impl = implementation_template.format(name = self.name, name_lower = self.name.lower(), functions = '\n\n'.join(function_bodies))