pimgen: Switch to new Mako templates
A substantial structural update to pimgen.
The existing template and supporting code is difficult
to enhance. Given that the code being generated by
pimgen is primarily a large map, with map elements being
initialized by simple types, initializers lists or the result
of method calls - structure pimgen types in a way that track
these givens.
yaml: Simplify the yaml structures.
MethodCall: become an argument.
Mako: Simplify main template.
Use new convenience types.
Use new decorator types.
Remove unused function throughout.
Change-Id: I1c3c16776ef8d5d7e005142999817e0371f9ce89
Signed-off-by: Brad Bishop <bradleyb@fuzziesquirrel.com>
diff --git a/README.md b/README.md
index 1b06514..14bc532 100644
--- a/README.md
+++ b/README.md
@@ -40,7 +40,8 @@
Supported filter tags are:
* name - The filter to use.
-* args - An optional list of arguments to pass to the filter.
+
+Subsequent tags are defined by the filter type.
The available filters provided by PIM are:
@@ -61,7 +62,8 @@
Supported action tags are:
* name - The action to perform.
-* args - An optional list of arguments to pass to the action.
+
+Subsequent tags are defined by the action type.
The available actions provided by PIM are:
diff --git a/example/events.d/match1.yaml b/example/events.d/match1.yaml
index 19d501a..d419c74 100644
--- a/example/events.d/match1.yaml
+++ b/example/events.d/match1.yaml
@@ -15,20 +15,18 @@
member: PropertiesChanged
filters:
- name: propertyChangedTo
- args:
- interface: xyz.openbmc_project.Example.Iface2
- property: ExampleProperty2
- value:
- type: string
- value: yyyxxx
+ interface: xyz.openbmc_project.Example.Iface2
+ property: ExampleProperty2
+ value:
+ type: string
+ value: yyyxxx
actions:
- name: setProperty
- args:
- interface: xyz.openbmc_project.Example.Iface1
- property: ExampleProperty1
- path: /changeme
- value:
- type: string
- value: changed
+ interface: xyz.openbmc_project.Example.Iface1
+ property: ExampleProperty1
+ path: /changeme
+ value:
+ type: string
+ value: changed
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
diff --git a/example/events.d/match2.yaml b/example/events.d/match2.yaml
index 84b28f1..5fe2388 100644
--- a/example/events.d/match2.yaml
+++ b/example/events.d/match2.yaml
@@ -15,19 +15,16 @@
member: PropertiesChanged
filters:
- name: propertyChangedTo
- args:
- interface: xyz.openbmc_project.Example.Iface2
- property: ExampleProperty2
- value:
- type: string
- value: xxxyyy
+ interface: xyz.openbmc_project.Example.Iface2
+ property: ExampleProperty2
+ value:
+ type: string
+ value: xxxyyy
actions:
- name: destroyObject
- args:
- path: /deleteme1
+ path: /deleteme1
- name: destroyObject
- args:
- path: /deleteme2
+ path: /deleteme2
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
diff --git a/generated.mako.cpp b/generated.mako.cpp
index a024d19..12d783b 100644
--- a/generated.mako.cpp
+++ b/generated.mako.cpp
@@ -14,6 +14,8 @@
namespace manager
{
+using namespace std::literals::string_literals;
+
const Manager::Makers Manager::_makers{
% for i in interfaces:
{
@@ -31,66 +33,7 @@
% if e.description:
// ${e.description.strip()}
% endif
- std::make_tuple(
- std::vector<details::EventBasePtr>(
- {
- % if e.cls == 'match':
- std::make_shared<details::DbusSignal>(
- % for i, s in enumerate(e.signatures[0].sig.items()):
- % if i == 0:
- ${'"{0}=\'{1}\',"'.format(*s)}
- % elif i + 1 == len(e.signatures[0].sig):
- ${'"{0}=\'{1}\'"'.format(*s)},
- % else:
- ${'"{0}=\'{1}\',"'.format(*s)}
- % endif
- % endfor
- % if e.filters[0].pointer:
- details::make_filter(${e.filters[0].bare_method()})),
- % else:
- % if e.filters[0].args:
- details::make_filter(
- ${e.filters[0].bare_method()}(
- % for i, arg in enumerate(e.filters[0].args):
- % if i + 1 != len(e.filters[0].args):
- ${arg.cppArg()},
- % else:
- ${arg.cppArg()}))),
- % endif
- % endfor
- % else:
- details::make_filter(
- ${e.filters[0].bare_method()}()),
- % endif
- % endif
- % endif
- }
- ),
- std::vector<details::ActionBasePtr>(
- {
- % for action in e.actions:
- % if action.pointer:
- details::make_action(${action.bare_method()}),
- % else:
- % if action.args:
- details::make_action(
- ${action.bare_method()}(
- % for i, arg in enumerate(action.args):
- % if i + 1 != len(action.args):
- ${arg.cppArg()},
- % else:
- ${arg.cppArg()})),
- % endif
- % endfor
- % else:
- details::make_action(
- ${action.bare_method()}()),
- % endif
- % endif
- % endfor
- }
- )
- )
+ ${e.call(loader, indent=indent +2)},
},
%endfor
};
diff --git a/pimgen.py b/pimgen.py
index 0e5ee25..86643aa 100755
--- a/pimgen.py
+++ b/pimgen.py
@@ -135,7 +135,6 @@
if kw.get('type', None) == 'string':
self.decorators.insert(0, Quote())
- self.cast = kw.pop('cast', None)
super(TrivialArgument, self).__init__(**kw)
def argument(self, loader, indent):
@@ -145,18 +144,6 @@
return a
- def cppArg(self):
- '''Transform string types to c++ string constants.'''
-
- a = self.value
- if self.type == 'string':
- a = '"%s"' % a
-
- if self.cast:
- a = 'static_cast<%s>(%s)' % (self.cast, a)
-
- return a
-
class InitializerList(Argument):
'''Initializer list arguments.'''
@@ -189,27 +176,15 @@
indent=indent)
-class MethodCall(NamedElement, Renderer):
+class MethodCall(Argument):
'''Render syntatically correct c++ method calls.'''
def __init__(self, **kw):
self.namespace = kw.pop('namespace', [])
- self.template = kw.pop('template', '')
- self.pointer = kw.pop('pointer', False)
- self.args = \
- [TrivialArgument(**x) for x in kw.pop('args', [])]
+ self.templates = kw.pop('templates', [])
+ self.args = kw.pop('args', [])
super(MethodCall, self).__init__(**kw)
- def bare_method(self):
- '''Provide the method name and encompassing
- namespace without any arguments.'''
-
- m = '::'.join(self.namespace + [self.name])
- if self.template:
- m += '<%s>' % self.template
-
- return m
-
def call(self, loader, indent):
return self.render(
loader,
@@ -247,83 +222,119 @@
super(Wrapper, self).__init__(**kw)
-class Filter(MethodCall):
- '''Provide common attributes for any filter.'''
+class Filter(Wrapper):
+ '''Convenience type for filters'''
def __init__(self, **kw):
+ kw['wrapper_name'] = 'make_filter'
+ kw['wrapper_namespace'] = ['details']
kw['namespace'] = ['filters']
super(Filter, self).__init__(**kw)
-class Action(MethodCall):
- '''Provide common attributes for any action.'''
+class Action(Wrapper):
+ '''Convenience type for actions'''
def __init__(self, **kw):
+ kw['wrapper_name'] = 'make_action'
+ kw['wrapper_namespace'] = ['details']
kw['namespace'] = ['actions']
super(Action, self).__init__(**kw)
class DestroyObject(Action):
- '''Render a destroyObject action.'''
+ '''Assemble a destroyObject action.'''
def __init__(self, **kw):
- mapped = kw.pop('args')
- kw['args'] = [
- {'value': mapped['path'], 'type':'string'},
- ]
+ args = [TrivialArgument(value=kw.pop('path'), type='string')]
+ kw['args'] = args
super(DestroyObject, self).__init__(**kw)
class SetProperty(Action):
- '''Render a setProperty action.'''
+ '''Assemble a setProperty action.'''
def __init__(self, **kw):
- mapped = kw.pop('args')
- member = Interface(mapped['interface']).namespace()
+ args = []
+
+ value = kw.pop('value')
+ prop = kw.pop('property')
+ iface = kw.pop('interface')
+ iface = Interface(iface)
+ namespace = iface.namespace().split('::')[:-1]
+ name = iface[-1]
+ t = Template(namespace=namespace, name=iface[-1])
+
member = '&%s' % '::'.join(
- member.split('::') + [NamedElement(
- name=mapped['property']).camelCase])
+ namespace + [name, NamedElement(name=prop).camelCase])
+ member_type = cppTypeName(value['type'])
+ member_cast = '{0} ({1}::*)({0})'.format(member_type, t.qualified())
- memberType = cppTypeName(mapped['value'].get('type'))
+ args.append(TrivialArgument(value=kw.pop('path'), type='string'))
+ args.append(TrivialArgument(value=str(iface), type='string'))
+ args.append(TrivialArgument(
+ value=member, decorators=[Cast('static', member_cast)]))
+ args.append(TrivialArgument(**value))
- kw['template'] = Interface(mapped['interface']).namespace()
- kw['args'] = [
- {'value': mapped['path'], 'type':'string'},
- {'value': mapped['interface'], 'type':'string'},
- {'value': member, 'cast': '{0} ({1}::*)({0})'.format(
- memberType,
- Interface(mapped['interface']).namespace())},
- mapped['value'],
- ]
+ kw['templates'] = [Template(name=name, namespace=namespace)]
+ kw['args'] = args
super(SetProperty, self).__init__(**kw)
class PropertyChanged(Filter):
- '''Render a propertyChanged filter.'''
+ '''Assemble a propertyChanged filter.'''
def __init__(self, **kw):
- mapped = kw.pop('args')
- kw['args'] = [
- {'value': mapped['interface'], 'type':'string'},
- {'value': mapped['property'], 'type':'string'},
- mapped['value']
- ]
+ args = []
+ args.append(TrivialArgument(value=kw.pop('interface'), type='string'))
+ args.append(TrivialArgument(value=kw.pop('property'), type='string'))
+ args.append(TrivialArgument(
+ decorators=[
+ Literal(kw['value'].get('type', None))], **kw.pop('value')))
+ kw['args'] = args
super(PropertyChanged, self).__init__(**kw)
-class Event(NamedElement, Renderer):
- '''Render an inventory manager event.'''
+class Event(MethodCall):
+ '''Assemble an inventory manager event.'''
action_map = {
'destroyObject': DestroyObject,
'setProperty': SetProperty,
}
+ filter_map = {
+ 'propertyChangedTo': PropertyChanged,
+ }
+
def __init__(self, **kw):
- self.cls = kw.pop('type')
- self.actions = \
- [self.action_map[x['name']](**x)
- for x in kw.pop('actions', [])]
+ self.summary = kw.pop('name')
+
+ filters = [
+ self.filter_map[x['name']](**x) for x in kw.pop('filters', [])]
+
+ event = MethodCall(
+ name='make_shared',
+ namespace=['std'],
+ templates=[Template(
+ name=kw.pop('event'),
+ namespace=kw.pop('event_namespace', []))],
+ args=kw.pop('event_args', []) + [filters[0]])
+
+ events = Vector(
+ templates=[Template(name='EventBasePtr', namespace=['details'])],
+ args=[event])
+
+ action_type = Template(name='ActionBasePtr', namespace=['details'])
+ action_args = [
+ self.action_map[x['name']](**x) for x in kw.pop('actions', [])]
+ actions = Vector(
+ templates=[action_type],
+ args=action_args)
+
+ kw['name'] = 'make_tuple'
+ kw['namespace'] = ['std']
+ kw['args'] = [events, actions]
super(Event, self).__init__(**kw)
@@ -331,16 +342,12 @@
'''Associate one or more dbus signal match signatures with
a filter.'''
- filter_map = {
- 'propertyChangedTo': PropertyChanged,
- }
-
def __init__(self, **kw):
- self.signatures = \
- [DbusSignature(**x) for x in kw.pop('signatures', [])]
- self.filters = \
- [self.filter_map[x['name']](**x)
- for x in kw.pop('filters')]
+ kw['event'] = 'DbusSignal'
+ kw['event_namespace'] = ['details']
+ kw['event_args'] = [
+ DbusSignature(**x) for x in kw.pop('signatures', [])]
+
super(MatchEvent, self).__init__(**kw)