xo-facet: expand genfacet.py, generate IFoo_Any.hpp

This commit is contained in:
Roland Conybeare 2025-12-24 23:11:14 -05:00
commit 66bd3380aa
4 changed files with 163 additions and 11 deletions

View file

@ -1,4 +1,4 @@
/** @file {{ abstract_facet_fname }}
/** @file {{abstract_facet_fname}}
*
* Generated automagically from ingredients:
* 1. code generator:
@ -17,24 +17,56 @@
{% for include_fname in facet_includes %}
#include {{include_fname}}
{% endfor %}
#include <xo/facet/obj.hpp>
#include <xo/facet/facet_implementation.hpp>
#include <xo/facet/typeseq.hpp>
namespace {{facet_ns1}} {
namespace {{facet_ns2}} {
using Copaque = const void *;
using Opaque = void *;
/**
{{abstract_facet_doc}}
**/
class {{abstract_facet}} {
public:
{% for method in methods %}
// types
{% for ty in types %}
/** {{ty.doc}} **/
using {{ty.name}} = {{ty.definition}};
{% endfor %}
/** {{method.doc}} **/
virtual {{method.return_type}} {{method.name}}({{method.args | args}}) {{method | qualifiers}} = 0;
// const methods
/** RTTI: unique id# for actual runtime data representation **/
virtual int32_t _typeseq() const noexcept = 0;
{% for md in const_methods %}
/** {{md.doc}} **/
virtual {{md.return_type}} {{md.name}}({{md.args | args}}) {{md | qualifiers}} = 0;
{% endfor %}
// nonconst methods
{% for md in nonconst_methods %}
/** {{md.doc}} **/
virtual {{md.return_type}} {{md.name}}({{md.args | args}}) {{md | qualifiers}} = 0;
{% endfor %}
}; /*{{abstract_facet}}*/
/** Implementation {{iface_facet}}_DRepr of {{abstract_facet}} for state DRepr
* should provide a specialization:
*
* template <>
* struct xo::facet::FacetImplementation<{{abstract_facet}}, DRepr> {
* using Impltype = {{iface_facet}}_DRepr;
* };
*
* then {{iface_facet_impltype}}<DRepr> --> {{iface_facet}}_DRepr
**/
template <typename DRepr>
using {{iface_facet_impltype}} = xo::facet::FacetImplType<{{abstract_facet}}, DRepr>;
} /*namespace {{facet_ns2}}*/
} /*namespace {{facet_ns1}}*/
/* {{abstract_face_fname}} */

View file

@ -32,6 +32,9 @@ def format_args(args, include_names=True):
else:
return ', '.join(p['type'] for p in args)
def format_args_nonames(args):
return format_args(args, False)
def format_arg_names(args):
""" Format argument names, for forwarding
"""
@ -61,6 +64,7 @@ def main():
# custom filters
env.filters['qualifiers'] = format_method_qualifiers
env.filters['args'] = format_args
env.filters['argtypes'] = format_args_nonames
env.filters['argnames'] = format_arg_names
facet_includes = idl['includes']
@ -69,12 +73,29 @@ def main():
facet_name = idl['facet'] # e.g. Sequence
facet_brief = idl['brief']
facet_doc = '\n'.join(idl['doc'])
methods = idl['methods']
for method in methods:
method['doc'] = '\n'.join(method['doc'])
types = idl['types']
for ty in types:
ty['doc'] = '\n'.join(ty['doc'])
const_methods = idl['const_methods']
for md in const_methods:
md['args'] = [{'type': "Copaque", 'name': "data"}] + md['args']
md['doc'] = '\n'.join(md['doc'])
nonconst_methods = idl['nonconst_methods']
for md in nonconst_methods:
md['args'] = [{'type': "Opaque", 'name': "data"}] + md['args']
md['doc'] = '\n'.join(md['doc'])
abstract_facet = f'A{facet_name}'
abstract_facet_fname = f'{abstract_facet}.hpp'
#
iface_facet = f'I{facet_name}'
iface_facet_impltype = f'{iface_facet}_ImplType'
#
iface_facet_any = f'{iface_facet}_Any'
iface_facet_any_fname = f'{iface_facet_any}.hpp'
context = {
'genfacet': __file__,
@ -91,13 +112,25 @@ def main():
'abstract_facet_fname': abstract_facet_fname,
'abstract_facet_doc': facet_doc,
#
'methods': methods
'iface_facet': iface_facet,
'iface_facet_impltype': iface_facet_impltype,
#
'iface_facet_any': iface_facet_any,
'iface_facet_any_hpp_j2': 'iface_facet_any.hpp.j2',
'iface_facet_any_fname': iface_facet_any_fname,
#
'types': types,
#
'const_methods': const_methods,
#
'nonconst_methods': nonconst_methods,
}
# generate .hpp files
templates = {}
templates[abstract_facet_fname] = context['abstract_facet_hpp_j2']
templates[iface_facet_any_fname] = context['iface_facet_any_hpp_j2']
for output_file, template_name in templates.items():
print(f'output_file: [{output_file}]')
@ -105,11 +138,10 @@ def main():
template = env.get_template(template_name)
content = template.render(**context)
(output_dir / output_file).write_text(content)
print(f"Generated {output_dir}/{output_file}")
if __name__ == '__main__':
main()

View file

@ -0,0 +1,72 @@
/** @file {{iface_facet_any_fname}}
*
* Generated automagically from ingredients:
* 1. code generator:
* [{{genfacet}}]
* arguments:
* --input [{{genfacet_input}}]
* 2. jinja2 template for abstract facet .hpp file:
* [{{ iface_facet_any_hpp_j2 }}]
* 3. idl for facet methods
* [{{ idl_fname }}]
**/
#pragma once
#include "{{abstract_facet_fname}}"
#include <xo/facet/obj.hpp>
namespace {{facet_ns1}} { namespace {{facet_ns2}} { class {{iface_facet_any}}; } }
namespace xo {
namespace facet {
template <>
struct FacetImplementation<{{facet_ns1}}::{{facet_ns2}}::{{abstract_facet}},
DVariantPlaceholder>
{
using ImplType = {{facet_ns1}}::{{facet_ns2}}::{{iface_facet_any}};
};
}
}
namespace {{facet_ns1}} {
namespace {{facet_ns2}} {
/** @class {{iface_facet_any}}
* @brief {{abstract_facet}} implementation for empty variant instance
**/
class {{iface_facet_any}} : public {{abstract_facet}} {
public:
{% for ty in types %}
using {{ty.name}} = {{abstract_facet}}::{{ty.name}};
{% endfor %}
const {{abstract_facet}} * iface() const { return std::launder(this); }
// from {{abstract_facet}}
// const methods
int32_t _typeseq() const noexcept override { return s_typeseq; }
{% for md in const_methods %}
[[noreturn]] {{md.return_type}} {{md.name}}({{md.args | argtypes}}) {{md | qualifiers}} override { _fatal(); }
{% endfor %}
// nonconst methods
{% for md in nonconst_methods %}
[[noreturn]] {{md.return_type}} {{md.name}}({{md.args | argtypes}}) {{md | qualifiers}} override { _fatail(); }
{% endfor %}
private:
[[noreturn]] static void _fatal();
public:
static int32_t s_typeseq;
static bool _valid;
};
} /*namespace {{facet_ns2}} */
} /*namespace {{facet_ns1}} */
/* {{iface_facet_any_fname}} */