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)