xo-gc xo-object2 xo-facet: builds w/ ISequence,Dlist

This commit is contained in:
Roland Conybeare 2025-12-29 14:32:52 -05:00
commit afc44e71fa
26 changed files with 717 additions and 75 deletions

View file

@ -1646,14 +1646,17 @@ macro(xo_add_genfacet)
REQUIRED) REQUIRED)
message(STATUS "GENFACET_EXECUTABLE=${GENFACET_EXECUTABLE}") message(STATUS "GENFACET_EXECUTABLE=${GENFACET_EXECUTABLE}")
set(generatedFiles
${GF_OUTPUT_HPP_DIR}/${FACET}.hpp
${GF_OUTPUT_HPP_DIR}/${GF_OUTPUT_IMPL_SUBDIR}/A${FACET}.hpp
${GF_OUTPUT_HPP_DIR}/${GF_OUTPUT_IMPL_SUBDIR}/I${FACET}_Any.hpp
${GF_OUTPUT_HPP_DIR}/${GF_OUTPUT_IMPL_SUBDIR}/I${FACET}_Xfer.hpp
${GF_OUTPUT_HPP_DIR}/${GF_OUTPUT_IMPL_SUBDIR}/R${FACET}.hpp
${GF_OUTPUT_CPP_DIR}/I${FACET}_Any.cpp)
# Build the genfacet command # Build the genfacet command
add_custom_command( add_custom_command(
OUTPUT ${GF_OUTPUT_HPP_DIR}/${FACET}.hpp OUTPUT $generatedFiles
${GF_OUTPUT_HPP_DIR}/${GF_OUTPUT_IMPL_SUBDIR}/A${FACET}.hpp
${GF_OUTPUT_HPP_DIR}/${GF_OUTPUT_IMPL_SUBDIR}/I${FACET}_Any.hpp
${GF_OUTPUT_HPP_DIR}/${GF_OUTPUT_IMPL_SUBDIR}/I${FACET}_Xfer.hpp
${GF_OUTPUT_HPP_DIR}/${GF_OUTPUT_IMPL_SUBDIR}/R${FACET}.hpp
${GF_OUTPUT_CPP_DIR}/I${FACET}_Any.cpp
COMMAND ${GENFACET_EXECUTABLE} COMMAND ${GENFACET_EXECUTABLE}
--input ${GF_INPUT} --input ${GF_INPUT}
--output-hpp ${GF_OUTPUT_HPP_DIR} --output-hpp ${GF_OUTPUT_HPP_DIR}
@ -1666,7 +1669,50 @@ macro(xo_add_genfacet)
) )
# Create a target for this generation # Create a target for this generation
add_custom_target(${GF_TARGET} add_custom_target(${GF_TARGET} DEPENDS ${generatedFiles})
DEPENDS ${GF_GENERATED_FILES} endmacro()
)
macro(xo_add_genfacetimpl)
# Parse arguments
set(options "")
set(oneValueArgs
TARGET # Name for this generation target
FACET # facet name
REPR # representation name
INPUT # Input .json5 file
OUTPUT_HPP_DIR # Directory for .hpp files
OUTPUT_IMPL_SUBDIR # Subdirectory name for impl headers
OUTPUT_CPP_DIR # Directory for .cpp files
)
set(multiValueArgs "")
cmake_parse_arguments(GF "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
find_program(GENFACET_EXECUTABLE NAMES genfacet
HINTS ${CMAKE_SOURCE_DIR}/xo-facet/codegen
DOC "path to xo genfacet code generator"
REQUIRED)
message(STATUS "GENFACET_EXECUTABLE=${GENFACET_EXECUTABLE}")
set(generatedFiles
${GF_OUTPUT_HPP_DIR}/${FACET}.hpp
${GF_OUTPUT_HPP_DIR}/${GF_OUTPUT_IMPL_SUBDIR}/I${FACET}_D${REPR}.hpp
${GF_OUTPUT_CPP_DIR}/I${FACET}_D${REPR}.cpp)
# Build the genfacet command
add_custom_command(
OUTPUT ${generatedFiles}
COMMAND ${GENFACET_EXECUTABLE}
--input ${GF_INPUT}
--output-hpp ${GF_OUTPUT_HPP_DIR}
--output-impl-hpp ${GF_OUTPUT_IMPL_SUBDIR}
--output-cpp ${GF_OUTPUT_CPP_DIR}
DEPENDS ${GF_INPUT}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT "Generating facet source files from ${GF_INPUT}"
VERBATIM
)
# Create a target for this generation
add_custom_target(${GF_TARGET} DEPENDS ${generatedFiles})
endmacro() endmacro()

View file

@ -15,12 +15,22 @@ def format_method_qualifiers(method):
""" """
quals = [] quals = []
if method.get('const', False): if method.get('const', False):
quals.append('const') quals.append(' const')
if method.get('noexcept', False): if method.get('noexcept', False):
quals.append('noexcept') quals.append(' noexcept')
return ' '.join(quals) return ' '.join(quals)
def format_method_staticqual(method):
""" Build qualifier string for a static method: noexcet
"""
quals = []
if method.get('noexcept', False):
quals.append(' noexcept')
return ' '.join(quals)
def format_args(args, include_names=True): def format_args(args, include_names=True):
""" Format argument list for a method """ Format argument list for a method
""" """
@ -40,6 +50,12 @@ def format_arg_names(args):
names = [p['name'] for p in args] names = [p['name'] for p in args]
return ', '.join([f"_dcast({names[0]})"] + names[1:]) return ', '.join([f"_dcast({names[0]})"] + names[1:])
def format_arg_names_nodata(args):
""" Format argument names for forwarding, omit data ('self') arg
"""
names = [p['name'] for p in args[1:]]
return ', '.join(names)
def format_args_nodata(args): def format_args_nodata(args):
""" Format arguments, but exclude data arg """ Format arguments, but exclude data arg
""" """
@ -51,46 +67,21 @@ def format_args_routing(args):
names = [p['name'] for p in args] names = [p['name'] for p in args]
return ', '.join([f"O::data()"] + names[1:]) return ', '.join([f"O::data()"] + names[1:])
def main(): def format_args_impl(args, drepr):
parser = argparse.ArgumentParser() """ Format argument names, for implementation (IFoo_DRepr)
parser.add_argument('--input', required=True, help='input IDL JSON5 file') """
parser.add_argument('--output-impl-hpp', required=True, help='.hpp detail subdir') names = [f"{p['type']} {p['name']}" for p in args]
parser.add_argument('--output-hpp', required=True, help='.hpp output directory') return ', '.join([f"const {drepr} & self"] + names[1:])
parser.add_argument('--output-cpp', required=True, help='.cpp output directory')
args = parser.parse_args()
idl_fname = args.input def gen_facet(env,
idl = load_idl(idl_fname) idl_fname,
# idl,
output_hpp_dir = Path(args.output_hpp) input_json5,
output_hpp_dir.mkdir(parents=False, exist_ok=True) output_hpp_dir,
# output_impl_hpp_dir,
output_impl_hpp_subdir = Path(args.output_impl_hpp) output_cpp_dir):
output_impl_hpp_dir = Path(args.output_hpp) / output_impl_hpp_subdir
output_impl_hpp_dir.mkdir(parents=False, exist_ok=True)
#
output_cpp_dir = Path(args.output_cpp)
output_cpp_dir.mkdir(parents=False, exist_ok=True)
# setup jinja2
#template_dir = Path(args.templates)
template_dir = Path(__file__).parent
#template_dir = Path(__file__).parent / 'codegen'
print(f'template_dir: [{template_dir}]')
env = Environment(loader = FileSystemLoader(template_dir),
trim_blocks = True,
lstrip_blocks = True)
# 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
env.filters['argsnodata'] = format_args_nodata
env.filters['argrouting'] = format_args_routing
# true to insert doxygen markup in generated .hpp/.cpp files # true to insert doxygen markup in generated .hpp/.cpp files
using_dox = idl['using_doxygen'] using_dox = idl['using_doxygen']
@ -150,7 +141,7 @@ def main():
context = { context = {
'genfacet': __file__, 'genfacet': __file__,
'genfacet_input': args.input, 'genfacet_input': idl_fname,
'using_dox': using_dox, 'using_dox': using_dox,
'impl_hpp_subdir': output_impl_hpp_subdir, 'impl_hpp_subdir': output_impl_hpp_subdir,
# #
@ -225,5 +216,282 @@ def main():
print(f"Generated {out_dir}/{out_file}") print(f"Generated {out_dir}/{out_file}")
def gen_facet_impl(env,
idl_fname,
idl,
facet_idl,
output_hpp_dir,
output_impl_hpp_subdir,
output_cpp_dir):
# true to insert doxygen markup in generated .hpp/.cpp files
using_dox = idl['using_doxygen']
# extra include files (or perhaps other definitions)
# facet_includes: include section for AFoo.hpp:
# <xo/gc/GCObject.hpp>
facet_includes = facet_idl['includes']
# sequence
facet_detail_subdir = facet_idl['detail_subdir']
# xo - facet_ns1: outer namespace for facet [e.g. xo]
facet_ns1 = facet_idl['namespace1']
# scm - facet_ns2: nested namespace for facet [e.g. scm]
facet_ns2 = facet_idl['namespace2']
# Sequence - facet_name: facet name
facet_name = facet_idl['facet']
# sequence - facet_name_lc: lower case [e.g. sequence]
facet_name_lc = facet_name.lower()
# brief doc for facet
facet_brief = idl['brief']
# doc section for facet
facet_doc = '\n'.join(idl['doc'])
types = facet_idl['types']
for ty in types:
ty['doc'] = '\n'.join(ty['doc'])
const_methods = facet_idl['const_methods']
for md in const_methods:
md['args'] = [{'type': "Copaque",
'name': "data"}] + md['args']
md['doc'] = '\n'.join(md['doc'])
nonconst_methods = facet_idl['nonconst_methods']
for md in nonconst_methods:
md['args'] = [{'type': "Opaque",
'name': "data"}] + md['args']
md['doc'] = '\n'.join(md['doc'])
# Foo.hpp
facet_hpp_fname = f'{facet_name}.hpp'
# AFoo
abstract_facet = f'A{facet_name}'
# AFoo.hpp
abstract_facet_fname = f'{abstract_facet}.hpp'
# IFoo
iface_facet = f'I{facet_name}'
# IFoo_ImplType
iface_facet_impltype = f'{iface_facet}_ImplType'
#
# IFoo_Any
iface_facet_any = f'{iface_facet}_Any'
# IFoo_Any.hpp
iface_facet_any_hpp_fname = f'{iface_facet_any}.hpp'
# IFoo_Any.cpp
iface_facet_any_cpp_fname = f'{iface_facet_any}.cpp'
#
# IFoo_Xfer
iface_facet_xfer = f'{iface_facet}_Xfer'
# IFoo_Xfer.hpp
iface_facet_xfer_hpp_fname = f'{iface_facet_xfer}.hpp'
# IFoo_Xfer.cpp
iface_facet_xfer_cpp_fname = f'{iface_facet_xfer}.cpp'
#
# RFoo
router_facet = f'R{facet_name}'
# RFoo.hpp
router_facet_hpp_fname = f'{router_facet}.hpp'
# ================================================================
# vars for IFacet_DRepr
# ----------------------------------------------------------------
# DList
data_repr = idl['repr']
# dlist
data_repr_lc = data_repr.lower()
# DList.hpp
data_repr_hpp_fname = f'{data_repr}.hpp'
# repr_ns1: outer namespace for repr [e.g. xo].
# (need not match facet)
repr_ns1 = idl['namespace1']
# repr_ns2: nested namespace for repr [e.g. scm].
repr_ns2 = idl['namespace2']
# iface_facet_repr: IFoo_DRepr
iface_facet_repr = f'{iface_facet}_{data_repr}'
# iface_facet_repr_hpp_fname: IFoo_DRepr.hpp
iface_facet_repr_hpp_fname = f'{iface_facet_repr}.hpp'
# iface_facet_repr_cpp_fname: IFoo_DRepr.cpp
iface_facet_repr_cpp_fname = f'{iface_facet_repr}.cpp'
# ================================================================
context = {
'genfacet': __file__,
'genfacet_input': idl_fname,
'using_dox': using_dox,
'impl_hpp_subdir': output_impl_hpp_subdir,
#
'facet_hpp_j2': 'facet.hpp.j2',
'facet_includes': facet_includes,
'facet_detail_subdir': facet_detail_subdir,
'facet_ns1': facet_ns1,
'facet_ns2': facet_ns2,
'facet_name': facet_name,
'facet_name_lc': facet_name_lc,
'facet_hpp_fname': facet_hpp_fname,
#'name': facet_name,
'idl_fname': idl_fname,
#
'abstract_facet_hpp_j2': 'abstract_facet.hpp.j2',
'abstract_facet': abstract_facet,
'abstract_facet_fname': abstract_facet_fname,
'abstract_facet_doc': facet_doc,
#
'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_cpp_j2': 'iface_facet_any.cpp.j2',
'iface_facet_any_hpp_fname': iface_facet_any_hpp_fname,
'iface_facet_any_cpp_fname': iface_facet_any_cpp_fname,
#
'iface_facet_xfer': iface_facet_xfer,
'iface_facet_xfer_hpp_j2': 'iface_facet_xfer.hpp.j2',
'iface_facet_xfer_cpp_j2': 'iface_facet_xfer.cpp.j2',
'iface_facet_xfer_hpp_fname': iface_facet_xfer_hpp_fname,
'iface_facet_xfer_cpp_fname': iface_facet_xfer_cpp_fname,
#
'router_facet': router_facet,
'router_facet_hpp_j2': 'router_facet.hpp.j2',
'router_facet_hpp_fname': router_facet_hpp_fname,
#
'types': types,
#
'const_methods': const_methods,
#
'nonconst_methods': nonconst_methods,
# ----------------------------------------------------------------
# vars for IFacet_DRepr
# ----------------------------------------------------------------
'repr_ns1': repr_ns1,
'repr_ns2': repr_ns2,
#
'data_repr': data_repr,
'data_repr_lc': data_repr_lc,
'data_repr_hpp_fname': data_repr_hpp_fname,
#
'iface_facet_repr': iface_facet_repr,
'iface_facet_repr_hpp_j2': 'iface_facet_repr.hpp.j2',
'iface_facet_repr_hpp_fname': iface_facet_repr_hpp_fname,
'iface_facet_repr_cpp_j2': 'iface_facet_repr.cpp.j2',
'iface_facet_repr_cpp_fname': iface_facet_repr_cpp_fname,
#
}
# generate .hpp files
templates = {}
templates[iface_facet_repr_hpp_fname] = [output_hpp_dir,
context['iface_facet_repr_hpp_j2']]
templates[iface_facet_repr_cpp_fname] = [output_cpp_dir,
context['iface_facet_repr_cpp_j2']]
# templates[facet_hpp_fname] = [output_hpp_dir,
# context['facet_hpp_j2']]
# templates[abstract_facet_fname] = [output_impl_hpp_dir,
# context['abstract_facet_hpp_j2']]
# templates[iface_facet_any_hpp_fname] = [output_impl_hpp_dir,
# context['iface_facet_any_hpp_j2']]
# templates[iface_facet_any_cpp_fname] = [output_cpp_dir,
# context['iface_facet_any_cpp_j2']]
# templates[iface_facet_xfer_hpp_fname] = [output_impl_hpp_dir,
# context['iface_facet_xfer_hpp_j2']]
# templates[router_facet_hpp_fname] = [output_impl_hpp_dir,
# context['router_facet_hpp_j2']]
for out_file, record in templates.items():
out_dir = record[0]
template_name = record[1]
print(f'out_dir: [{out_dir}]')
print(f'out_file: [{out_file}]')
print(f'template_name: [{template_name}]')
template = env.get_template(template_name)
content = template.render(**context)
(out_dir / out_file).write_text(content)
print(f"Generated {out_dir}/{out_file}")
def main():
parser = argparse.ArgumentParser()
parser.add_argument('--input', required=True, help='input IDL JSON5 file')
# --output-impl-hpp: putting this in .json5, will be able to drop this.
parser.add_argument('--output-impl-hpp', required=True, help='.hpp detail subdir')
parser.add_argument('--output-hpp', required=True, help='.hpp output directory')
parser.add_argument('--output-cpp', required=True, help='.cpp output directory')
args = parser.parse_args()
idl_fname = args.input
idl = load_idl(idl_fname)
output_hpp_dir = Path(args.output_hpp)
output_hpp_dir.mkdir(parents=False, exist_ok=True)
# TODO: output_impl_hpp_subdir: use idl['detail_subdir'] instead
output_impl_hpp_subdir = Path(args.output_impl_hpp)
output_impl_hpp_dir = Path(args.output_hpp) / output_impl_hpp_subdir
output_impl_hpp_dir.mkdir(parents=False, exist_ok=True)
output_cpp_dir = Path(args.output_cpp)
output_cpp_dir.mkdir(parents=False, exist_ok=True)
# setup jinja2
#template_dir = Path(args.templates)
template_dir = Path(__file__).parent
#template_dir = Path(__file__).parent / 'codegen'
print(f'template_dir: [{template_dir}]')
env = Environment(loader = FileSystemLoader(template_dir),
trim_blocks = True,
lstrip_blocks = True)
# custom filters.
# A filter 'foo' provides ability to write '{{var | foo}}' to expand
# j2 variable 'var' to 'filters[foo](var)'
#
env.filters['qualifiers'] = format_method_qualifiers
env.filters['staticqual'] = format_method_staticqual
env.filters['args'] = format_args
env.filters['argtypes'] = format_args_nonames
env.filters['argnames'] = format_arg_names
env.filters['argnamesnodata'] = format_arg_names_nodata
env.filters['argsnodata'] = format_args_nodata
env.filters['argrouting'] = format_args_routing
env.filters['argimpl'] = format_args_impl
if idl['mode'] == 'facet':
gen_facet(env,
idl_fname,
idl,
output_hpp_dir,
output_impl_hpp_dir,
output_cpp_dir)
elif idl['mode'] == 'implementation':
facet_idl_fname = idl['facet_idl']
facet_idl = load_idl(facet_idl_fname)
gen_facet_impl(env,
idl_fname,
idl,
facet_idl,
output_hpp_dir,
output_impl_hpp_dir,
output_cpp_dir)
if __name__ == '__main__': if __name__ == '__main__':
main() main()

View file

@ -0,0 +1,34 @@
/** @file {{iface_facet_repr_cpp_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 }}]
**/
#include "{{iface_facet_repr_hpp_fname}}"
namespace {{repr_ns1}} {
namespace {{repr_ns2}} {
{% for md in const_methods %}
auto
{{iface_facet_repr}}::{{md.name}}({{md.args | argimpl(data_repr)}}){{md | staticqual}} -> {{md.return_type}}
{
{% if md.return_type == "void" %}
self.{{md.name}}({{md.args | argnamesnodata}});
{% else %}
return self.{{md.name}}({{md.args | argnamesnodata}});
{% endif %}
}
{% endfor %}
} /*namespace {{repr_ns2}}*/
} /*namespace {{repr_ns1}}*/
/* end {{iface_facet_repr_cpp_fname}} */

View file

@ -0,0 +1,70 @@
/** @file {{iface_facet_repr_hpp_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 "{{facet_hpp_fname}}"
#include "{{facet_detail_subdir}}/{{iface_facet_xfer_hpp_fname}}"
#include "{{data_repr_hpp_fname}}"
namespace {{repr_ns1}} { namespace {{repr_ns2}} { class {{iface_facet_repr}}; } }
namespace xo {
namespace facet {
template <>
struct FacetImplementation<{{facet_ns1}}::{{facet_ns2}}::{{abstract_facet}},
{{repr_ns1}}::{{repr_ns2}}::{{data_repr}}>
{
using ImplType = {{facet_ns1}}::{{facet_ns2}}::{{iface_facet_xfer}}
<{{repr_ns1}}::{{repr_ns2}}::{{data_repr}},
{{repr_ns1}}::{{repr_ns2}}::{{iface_facet_repr}}>;
};
}
}
namespace {{repr_ns1}} {
namespace {{repr_ns2}} {
/** @class {{iface_facet_repr}}
**/
class {{iface_facet_repr}} {
public:
{% if using_dox %}
/** @defgroup {{repr_ns2}}-{{facet_name_lc}}-{{data_repr_lc}}-type-traits **/
///@{
{% endif %}
{% for ty in types %}
using {{ty.name}} = {{abstract_facet}}::{{ty.name}};
{% endfor %}
{% if using_dox %}
///@}
/** @defgroup {{repr_ns2}}-{{facet_name_lc}}-{{data_repr_lc}}-methods **/
///@{
{% endif %}
{% for md in const_methods %}
/** {{md.doc}} **/
static {{md.return_type}} {{md.name}}({{md.args | argimpl(data_repr)}}){{md | staticqual}};
{% endfor %}
{% for md in methods %}
/** {{md.doc}} **/
static {{md.return_type}} {{md.name}}({{md.args | argimpl(data_repr)}}){{md | staticqual}};
{% endfor %}
{% if using_dox %}
///@}
{% endif %}
};
} /*namespace {{repr_ns2}}*/
} /*namespace {{repr_ns1}}*/
/* end */

View file

@ -5,7 +5,7 @@
#pragma once #pragma once
#include "IGCObject_Any.hpp" //#include "IGCObject_Any.hpp"
#include <xo/facet/facet_implementation.hpp> #include <xo/facet/facet_implementation.hpp>
#include <xo/facet/typeseq.hpp> #include <xo/facet/typeseq.hpp>
@ -22,6 +22,7 @@ namespace xo {
using Copaque = const void *; using Copaque = const void *;
using Opaque = void *; using Opaque = void *;
struct AGCObject;
struct IGCObject_Any; // see IGCObject_Any.hpp struct IGCObject_Any; // see IGCObject_Any.hpp
/** @class ACollector /** @class ACollector
@ -53,10 +54,12 @@ namespace xo {
virtual void install_type(Opaque d, int32_t tseq, IGCObject_Any & iface) = 0; virtual void install_type(Opaque d, int32_t tseq, IGCObject_Any & iface) = 0;
virtual void add_gc_root(Opaque d, int32_t tseq, Opaque * root) = 0; virtual void add_gc_root(Opaque d, int32_t tseq, Opaque * root) = 0;
/** evacuate @p *lhs to to-space and replace with forwarding pointer /** evacuate @p *lhs, that refers to state with interface @p lhs_iface,
* to collector @p d's to-space. Replace *lhs_data with forwarding pointer
*
* Require: gc in progress * Require: gc in progress
**/ **/
virtual void forward_inplace(Opaque d, obj<AGCObject> * lhs) = 0; virtual void forward_inplace(Opaque d, AGCObject * lhs_iface, void ** lhs_data) = 0;
}; };
} }

View file

@ -17,6 +17,8 @@ namespace xo {
using Copaque = const void *; using Copaque = const void *;
using Opaque = void *; using Opaque = void *;
struct ACollector;
/** @class AObject /** @class AObject
* @brief Abstract facet for collector-eligible data * @brief Abstract facet for collector-eligible data
* *
@ -30,9 +32,10 @@ namespace xo {
virtual int32_t _typeseq() const noexcept = 0; virtual int32_t _typeseq() const noexcept = 0;
virtual size_type shallow_size(Copaque d) const noexcept = 0; virtual size_type shallow_size(Copaque d) const noexcept = 0;
virtual Opaque * shallow_copy(Copaque d, virtual Opaque shallow_copy(Copaque d,
obj<AAllocator> mm) const noexcept = 0; obj<AAllocator> mm) const noexcept = 0;
virtual size_type forward_children(Opaque d) const noexcept = 0; virtual size_type forward_children(Opaque d,
obj<ACollector>) const noexcept = 0;
}; };
// implementation IGCObject_DRepr of AGCObject for state DRepr // implementation IGCObject_DRepr of AGCObject for state DRepr

View file

@ -36,7 +36,7 @@ namespace xo {
// non-const methods // non-const methods
[[noreturn]] void install_type(Opaque, int32_t, IGCObject_Any &) noexcept override { _fatal(); } [[noreturn]] void install_type(Opaque, int32_t, IGCObject_Any &) noexcept override { _fatal(); }
[[noreturn]] void add_gc_root(Opaque, int32_t, Opaque *) override { _fatal(); } [[noreturn]] void add_gc_root(Opaque, int32_t, Opaque *) override { _fatal(); }
[[noreturn]] void forward_inplace(Opaque, obj<AGCObject> *) override { _fatal(); } [[noreturn]] void forward_inplace(Opaque, AGCObject *, void **) override { _fatal(); }
private: private:
[[noreturn]] static void _fatal(); [[noreturn]] static void _fatal();

View file

@ -44,7 +44,7 @@ namespace xo {
static void install_type(DX1Collector & d, static void install_type(DX1Collector & d,
int32_t seq, IGCObject_Any & iface); int32_t seq, IGCObject_Any & iface);
static void add_gc_root(DX1Collector & d, int32_t tseq, Opaque * root); static void add_gc_root(DX1Collector & d, int32_t tseq, Opaque * root);
static void forward_inplace(DX1Collector & d, obj<AGCObject> * lhs); static void forward_inplace(DX1Collector & d, AGCObject * lhs_iface, void ** lhs_data);
static int32_t s_typeseq; static int32_t s_typeseq;
static bool _valid; static bool _valid;

View file

@ -49,8 +49,8 @@ namespace xo {
void add_gc_root(Opaque d, int32_t tseq, Opaque * root) override { void add_gc_root(Opaque d, int32_t tseq, Opaque * root) override {
I::add_gc_root(_dcast(d), tseq, root); I::add_gc_root(_dcast(d), tseq, root);
} }
void forward_inplace(Opaque d, obj<AGCObject> * lhs) override { void forward_inplace(Opaque d, AGCObject * lhs_iface, void ** lhs_data) override {
I::forward_inplace(_dcast(d), lhs); I::forward_inplace(_dcast(d), lhs_iface, lhs_data);
} }
private: private:

View file

@ -6,6 +6,7 @@
#pragma once #pragma once
#include "AGCObject.hpp" #include "AGCObject.hpp"
#include "Collector.hpp"
#include <new> #include <new>
namespace xo { namespace xo {
@ -31,9 +32,10 @@ namespace xo {
int32_t _typeseq() const noexcept override { return s_typeseq; } int32_t _typeseq() const noexcept override { return s_typeseq; }
[[noreturn]] size_type shallow_size(Copaque) const noexcept override { _fatal(); } [[noreturn]] size_type shallow_size(Copaque) const noexcept override { _fatal(); }
[[noreturn]] Opaque * shallow_copy(Copaque, [[noreturn]] Opaque shallow_copy(Copaque,
obj<AAllocator>) const noexcept override { _fatal(); } obj<AAllocator>) const noexcept override { _fatal(); }
[[noreturn]] size_type forward_children(Opaque) const noexcept override { _fatal(); } [[noreturn]] size_type forward_children(Opaque,
obj<ACollector>) const noexcept override { _fatal(); }
private: private:
[[noreturn]] static void _fatal(); [[noreturn]] static void _fatal();

View file

@ -6,6 +6,7 @@
#pragma once #pragma once
#include "AGCObject.hpp" #include "AGCObject.hpp"
#include "ACollector.hpp"
namespace xo { namespace xo {
namespace mm { namespace mm {
@ -28,16 +29,17 @@ namespace xo {
int32_t _typeseq() const noexcept override { return s_typeseq; } int32_t _typeseq() const noexcept override { return s_typeseq; }
size_type shallow_size(Copaque d) const noexcept override { size_type shallow_size(Copaque d) const noexcept override {
return I::shallow_copy(_dcast(d)); return I::shallow_size(_dcast(d));
} }
Opaque * shallow_copy(Copaque d, obj<AAllocator> mm) const noexcept override { Opaque shallow_copy(Copaque d, obj<AAllocator> mm) const noexcept override {
return I::shallow_size(_dcast(d), mm); return I::shallow_copy(_dcast(d), mm);
} }
// non-const methods // non-const methods
size_type forward_children(Opaque d) const noexcept override { size_type forward_children(Opaque d,
return I::forward_children(d); obj<ACollector> gc) const noexcept override {
return I::forward_children(_dcast(d), gc);
} }
private: private:

View file

@ -30,7 +30,7 @@ namespace xo {
void install_type(int32_t tseq, IGCObject_Any & iface) { return O::iface()->install_type(O::data(), tseq, iface); } void install_type(int32_t tseq, IGCObject_Any & iface) { return O::iface()->install_type(O::data(), tseq, iface); }
void add_gc_root(int32_t tseq, Opaque * root) { O::iface()->add_gc_root(O::data(), tseq, root); } void add_gc_root(int32_t tseq, Opaque * root) { O::iface()->add_gc_root(O::data(), tseq, root); }
void forward_inplace(obj<AGCObject> * lhs) { O::iface()->forward_inplace(O::data(), lhs); } void forward_inplace(AGCObject * lhs_iface, void ** lhs_data) { O::iface()->forward_inplace(O::data(), lhs_iface, lhs_data); }
static bool _valid; static bool _valid;
}; };

View file

@ -25,7 +25,7 @@ namespace xo {
int32_t _typeseq() const noexcept { return O::iface()->_typeseq(); } int32_t _typeseq() const noexcept { return O::iface()->_typeseq(); }
size_type shallow_size() const noexcept { O::iface()->shallow_size(O::data()); } size_type shallow_size() const noexcept { O::iface()->shallow_size(O::data()); }
Opaque * shallow_copy(obj<AAllocator> mm) const noexcept { O::iface()->shallow_copy(O::data(), mm); } Opaque shallow_copy(obj<AAllocator> mm) const noexcept { O::iface()->shallow_copy(O::data(), mm); }
size_type forward_children() noexcept { O::iface()->forward_children(O::data()); } size_type forward_children() noexcept { O::iface()->forward_children(O::data()); }
static bool _valid; static bool _valid;

View file

@ -73,8 +73,10 @@ namespace xo {
void void
ICollector_DX1Collector::forward_inplace(DX1Collector & d, ICollector_DX1Collector::forward_inplace(DX1Collector & d,
obj<AGCObject> * lhs) AGCObject * lhs_iface,
void ** lhs_data)
{ {
(void)lhs_iface;
assert(d.runstate_.is_running()); assert(d.runstate_.is_running());
/* /*
@ -90,7 +92,7 @@ namespace xo {
* +----------+ * +----------+
*/ */
void * object_data = (byte *)(*lhs).opaque_data(); void * object_data = (byte *)lhs_data;
if (!d.contains(role::from_space(), object_data)) { if (!d.contains(role::from_space(), object_data)) {
/* *lhs isn't in GC-allocated space. /* *lhs isn't in GC-allocated space.
@ -143,7 +145,7 @@ namespace xo {
void * dest = *(void**)object_data; void * dest = *(void**)object_data;
/* update *lhs in-place */ /* update *lhs in-place */
(*lhs).reset_opaque(dest); *lhs_data = dest;
} else if (check_move_policy(d, alloc_hdr, object_data)) { } else if (check_move_policy(d, alloc_hdr, object_data)) {
/* copy object *lhs + replace with forwarding pointer */ /* copy object *lhs + replace with forwarding pointer */

View file

@ -27,6 +27,16 @@ xo_add_genfacet(
OUTPUT_CPP_DIR src/object2 OUTPUT_CPP_DIR src/object2
) )
xo_add_genfacetimpl(
TARGET xo-object2-facetimpl-sequence-list
FACET Sequence
REPR List
INPUT idl/ISequence_DList.json5
OUTPUT_HPP_DIR include/xo/object2
OUTPUT_IMPL_SUBDIR sequence
OUTPUT_CPP_DIR src/object2
)
# ---------------------------------------------------------------- # ----------------------------------------------------------------
# must complete definition of expression lib before configuring examples # must complete definition of expression lib before configuring examples

View file

@ -0,0 +1,12 @@
{
mode: "implementation",
includes: [],
namespace1: "xo",
namespace2: "scm",
facet_idl: "idl/Sequence.json5",
brief: "provide ASequence interface for DList state",
using_doxygen: true,
repr: "DList",
doc: [ "doc for something or other"
],
}

View file

@ -1,8 +1,10 @@
{ {
mode: "facet",
includes: ["<xo/gc/GCObject.hpp>"], includes: ["<xo/gc/GCObject.hpp>"],
namespace1: "xo", namespace1: "xo",
namespace2: "scm", namespace2: "scm",
facet: "Sequence", facet: "Sequence",
detail_subdir: "sequence",
brief: "an ordered collection of variants", brief: "an ordered collection of variants",
using_doxygen: true, using_doxygen: true,
doc: [ doc: [

View file

@ -11,13 +11,23 @@ namespace xo {
namespace scm { namespace scm {
struct DList { struct DList {
using size_type = std::size_t;
using AGCObject = xo::mm::AGCObject; using AGCObject = xo::mm::AGCObject;
DList(xo::obj<AGCObject> h, DList(xo::obj<AGCObject> h,
xo::obj<AGCObject> r) : head_{h}, rest_{r} {} DList * r) : head_{h}, rest_{r} {}
/** DList length is at least 1 **/
bool is_empty() const noexcept { return false; };
/** DList models a finite sequence **/
bool is_finite() const noexcept { return true; };
/** return number of elements in this DList **/
size_type size() const noexcept;
/** return element at 0-based index @p ix **/
obj<AGCObject> at(size_type ix) const;
obj<AGCObject> head_; obj<AGCObject> head_;
obj<AGCObject> rest_; DList * rest_ = nullptr;
}; };
} /*namespace scm*/ } /*namespace scm*/

View file

@ -5,6 +5,7 @@
#pragma once #pragma once
#include <xo/gc/Collector.hpp>
#include <xo/alloc2/alloc/AAllocator.hpp> #include <xo/alloc2/alloc/AAllocator.hpp>
#include <xo/gc/detail/AGCObject.hpp> #include <xo/gc/detail/AGCObject.hpp>
#include <xo/gc/detail/IGCObject_Xfer.hpp> #include <xo/gc/detail/IGCObject_Xfer.hpp>

View file

@ -5,6 +5,7 @@
#pragma once #pragma once
#include <xo/gc/Collector.hpp>
#include "xo/alloc2/alloc/AAllocator.hpp" #include "xo/alloc2/alloc/AAllocator.hpp"
#include <xo/gc/detail/AGCObject.hpp> #include <xo/gc/detail/AGCObject.hpp>
#include <xo/gc/detail/IGCObject_Xfer.hpp> #include <xo/gc/detail/IGCObject_Xfer.hpp>

View file

@ -13,6 +13,19 @@
#include "DList.hpp" #include "DList.hpp"
namespace xo { namespace xo {
namespace scm { struct IGCObject_DList; }
namespace facet {
template <>
struct FacetImplementation<xo::mm::AGCObject,
xo::scm::DList>
{
using ImplType = xo::mm::IGCObject_Xfer
<xo::scm::DList,
xo::scm::IGCObject_DList>;
};
}
namespace scm { namespace scm {
/* changes here coordinate with: /* changes here coordinate with:
* IGCObject_XFer * IGCObject_XFer

View file

@ -0,0 +1,61 @@
/** @file ISequence_DList.hpp
*
* Generated automagically from ingredients:
* 1. code generator:
* [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet]
* arguments:
* --input [idl/ISequence_DList.json5]
* 2. jinja2 template for abstract facet .hpp file:
* [iface_facet_any.hpp.j2]
* 3. idl for facet methods
* [idl/ISequence_DList.json5]
**/
#pragma once
#include "Sequence.hpp"
#include "sequence/ISequence_Xfer.hpp"
#include "DList.hpp"
namespace xo { namespace scm { class ISequence_DList; } }
namespace xo {
namespace facet {
template <>
struct FacetImplementation<xo::scm::ASequence,
xo::scm::DList>
{
using ImplType = xo::scm::ISequence_Xfer
<xo::scm::DList,
xo::scm::ISequence_DList>;
};
}
}
namespace xo {
namespace scm {
/** @class ISequence_DList
**/
class ISequence_DList {
public:
/** @defgroup scm-sequence-dlist-type-traits **/
///@{
using size_type = ASequence::size_type;
using AGCObject = ASequence::AGCObject;
///@}
/** @defgroup scm-sequence-dlist-methods **/
///@{
/** true iff sequence is empty **/
static bool is_empty(const DList & self) noexcept;
/** true iff sequence is finite **/
static bool is_finite(const DList & self) noexcept;
/** return element @p index of this sequence **/
static obj<AGCObject> at(const DList & self, size_type index);
///@}
};
} /*namespace scm*/
} /*namespace xo*/
/* end */

View file

@ -6,9 +6,12 @@ set(SELF_SRCS
IGCObject_DInteger.cpp IGCObject_DInteger.cpp
IGCObject_DList.cpp IGCObject_DList.cpp
ISequence_Any.cpp ISequence_Any.cpp
ISequence_DList.cpp
DList.cpp
) )
xo_add_shared_library4(${SELF_LIB} ${PROJECT_NAME}Targets ${PROJECT_VERSION} 1 ${SELF_SRCS}) xo_add_shared_library4(${SELF_LIB} ${PROJECT_NAME}Targets ${PROJECT_VERSION} 1 ${SELF_SRCS})
# note: deps here must also appear in cmake/xo_alloc2Config.cmake.in # note: deps here must also appear in cmake/xo_alloc2Config.cmake.in
xo_dependency(${SELF_LIB} xo_gc) xo_dependency(${SELF_LIB} xo_gc)
#xo_dependency(${SELF_LIB} indentlog) #xo_dependency(${SELF_LIB} indentlog)
#add_dependencies(${SELF_LIB} xo-object2-facetimpl-sequence-list)

View file

@ -0,0 +1,54 @@
/** @file DList.cpp
*
* @author Roland Conybeare, Dec 2025
**/
#include "DList.hpp"
#include <xo/indentlog/print/tag.hpp>
namespace xo {
namespace scm {
auto
DList::size() const noexcept -> size_type
{
const DList * l = this;
size_type z = 0;
while (l) {
++z;
l = l->rest_;
}
return z;
}
auto
DList::at(size_type index) const -> obj<AGCObject>
{
size_type ix = index;
const DList * l = this;
while (l->rest_ && (ix > 0)) {
--ix;
l = l->rest_;
}
if (ix > 0) {
assert(l == nullptr);
throw std::runtime_error
(tostr("DList::at: out-of-range index where [0..z) expected",
xtag("index", index),
xtag("z", this->size())));
}
assert(l);
return l->head_;
}
} /*namespace scm*/
} /*namespace xo*/
/* end DList.cpp */

View file

@ -6,7 +6,9 @@
#include "IGCObject_DList.hpp" #include "IGCObject_DList.hpp"
namespace xo { namespace xo {
using xo::mm::AGCObject;
using xo::mm::AAllocator; using xo::mm::AAllocator;
using xo::facet::with_facet;
using xo::facet::obj; using xo::facet::obj;
using std::size_t; using std::size_t;
@ -33,8 +35,11 @@ namespace xo {
IGCObject_DList::forward_children(DList & src, IGCObject_DList::forward_children(DList & src,
obj<ACollector> gc) noexcept obj<ACollector> gc) noexcept
{ {
gc.forward_inplace(&src.head_); gc.forward_inplace(src.head_.iface(), (void **)&(src.head_.data_));
gc.forward_inplace(&src.rest_);
//auto rest = with_facet<AGCObject>::mkobj(src.rest_);
xo::facet::FacetImplementation<xo::mm::AGCObject, DList>::ImplType iface;
gc.forward_inplace(&iface, (void **)(&src.rest_));
return shallow_size(src); return shallow_size(src);
} }

View file

@ -0,0 +1,40 @@
/** @file ISequence_DList.cpp
*
* Generated automagically from ingredients:
* 1. code generator:
* [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet]
* arguments:
* --input [idl/ISequence_DList.json5]
* 2. jinja2 template for abstract facet .hpp file:
* [iface_facet_any.hpp.j2]
* 3. idl for facet methods
* [idl/ISequence_DList.json5]
**/
#include "ISequence_DList.hpp"
namespace xo {
namespace scm {
auto
ISequence_DList::is_empty(const DList & self) noexcept -> bool
{
return self.is_empty();
}
auto
ISequence_DList::is_finite(const DList & self) noexcept -> bool
{
return self.is_finite();
}
auto
ISequence_DList::at(const DList & self, size_type index) -> obj<AGCObject>
{
return self.at(index);
}
} /*namespace scm*/
} /*namespace xo*/
/* end ISequence_DList.cpp */