diff options
-rwxr-xr-x | bin/generate-dummy-class.py | 23 | ||||
-rw-r--r-- | lib/aspectc.py | 2 | ||||
-rw-r--r-- | lib/codegen.py | 80 |
3 files changed, 104 insertions, 1 deletions
diff --git a/bin/generate-dummy-class.py b/bin/generate-dummy-class.py new file mode 100755 index 0000000..2200486 --- /dev/null +++ b/bin/generate-dummy-class.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python3 + +from aspectc import Repo +from codegen import MultipassDriver +from automata import PTA +import yaml + +with open('/home/derf/var/projects/multipass/model/driver/nrf24l01.dfa', 'r') as f: + driver_definition = yaml.safe_load(f) + pta = PTA.from_yaml(driver_definition) +repo = Repo('/home/derf/var/projects/multipass/build/repo.acp') + +enum = dict() + +if 'dummygen' in driver_definition and 'enum' in driver_definition['dummygen']: + enum = driver_definition['dummygen']['enum'] + +drv = MultipassDriver('Nrf24l01', pta, repo.class_by_name['Nrf24l01'], enum=enum) + +with open('/home/derf/var/projects/multipass/src/driver/dummy.cc', 'w') as f: + f.write(drv.impl) +with open('/home/derf/var/projects/multipass/include/driver/dummy.h', 'w') as f: + f.write(drv.header) diff --git a/lib/aspectc.py b/lib/aspectc.py index 919c93d..3229057 100644 --- a/lib/aspectc.py +++ b/lib/aspectc.py @@ -7,7 +7,7 @@ class AspectCClass: :attr name: class name (str) :attr class_id: internal AspectC++ class ID (str/int) :attr functions: functions implemented by this class (list of :class:`AspectCFunction`) - :attr function: dict mapping function name to :class:`AspectCFunction` + :attr function: dict mapping function name to :class:`AspectCFunction`. Only sensible for classes which do not overload functions. """ def __init__(self, name, class_id, functions): diff --git a/lib/codegen.py b/lib/codegen.py new file mode 100644 index 0000000..d6dfe6e --- /dev/null +++ b/lib/codegen.py @@ -0,0 +1,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} ©); + +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] + function_arguments = list() + + if len(transition.arguments) != len(function_info.argument_types): + # polymorphic function variant, TODO + pass + + 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)) |