Skip to content

Commit

Permalink
[sourcegen] Add vector<shared_ptr<T>> handling
Browse files Browse the repository at this point in the history
Also fix issues caused by differences of doxygen and Cantera whitespace
conventions in argument lists and add recipes for functions used in
googletests.
  • Loading branch information
ischoegl committed Jan 4, 2025
1 parent ed2f2de commit 4a7f97f
Show file tree
Hide file tree
Showing 8 changed files with 66 additions and 19 deletions.
3 changes: 2 additions & 1 deletion interfaces/sourcegen/sourcegen/_data/ctkin_auto.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ parents: [] # List of parent classes
derived: [] # List of specializations
recipes:
- name: nReactions
# - name: getFwdRatesOfProgress
- name: kineticsType
- name: getFwdRatesOfProgress
- name: del
what: noop
brief: Destructor; required by some APIs although object is managed by Solution.
Expand Down
5 changes: 3 additions & 2 deletions interfaces/sourcegen/sourcegen/_data/ctsol_auto.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ recipes:
- name: newSolution
implements: newSolution(const string&, const string&, const string&)
uses: [thermo, kinetics, transport]
- name: newInterface # currently disabled in CLib's config.yaml
- name: newInterface
implements:
newInterface(const string&, const string&, const vector<shared_ptr<Solution>>&)
uses: [thermo, kinetics]
Expand All @@ -23,10 +23,11 @@ recipes:
- name: thermo
- name: kinetics
- name: transport
- name: setTransport
- name: setTransport # currently disabled in CLib's config.yaml
- name: nAdjacent
- name: adjacent
implements: Solution::adjacent(size_t)
uses: [thermo, kinetics, transport]
what: constructor # registers object in CLib storage
# - name: adjacentName
- name: cabinetSize
13 changes: 13 additions & 0 deletions interfaces/sourcegen/sourcegen/_data/ctthermo_auto.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,19 @@ recipes:
implements: Phase::setMoleFractionsByName(const string&)
- name: setMassFractionsByName
implements: Phase::setMassFractionsByName(const string&)
- name: enthalpy_mole
- name: enthalpy_mass
- name: entropy_mole
- name: entropy_mass
- name: intEnergy_mole
- name: intEnergy_mass
- name: cp_mole
- name: cp_mass
- name: getPartialMolarEnthalpies
- name: getPartialMolarEntropies
- name: getPartialMolarIntEnergies
- name: getPartialMolarCp
- name: getPartialMolarVolumes
- name: equilibrate
implements:
ThermoPhase::equilibrate(const string&, const string&, double, int, int, int)
Expand Down
1 change: 1 addition & 0 deletions interfaces/sourcegen/sourcegen/_data/cttrans_auto.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ recipes:
- name: transportModel
- name: viscosity
- name: thermalConductivity
- name: getMixDiffCoeffs
- name: del
what: noop
brief: Destructor; required by some APIs although object is managed by Solution.
Expand Down
2 changes: 1 addition & 1 deletion interfaces/sourcegen/sourcegen/_dataclasses.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def from_xml(cls, param: str) -> 'Param':
Note: Converts from doxygen style to simplified C++ whitespace notation.
"""
for rep in [(" &", "& "), ("< ", "<"), (" >", ">")]:
for rep in [(" &", "& "), ("< ", "<"), (" >", ">"), (" *", "* ")]:
param = param.replace(*rep)
return cls.from_str(param.strip())

Expand Down
52 changes: 40 additions & 12 deletions interfaces/sourcegen/sourcegen/clib/_CLibSourceGenerator.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
class CLibSourceGenerator(SourceGenerator):
"""The SourceGenerator for generating CLib."""

_clib_bases: list[str] = None #: list of bases provided via YAML configurations

def __init__(self, out_dir: str, config: dict, templates: dict):
self._out_dir = out_dir or None
if self._out_dir is not None:
Expand Down Expand Up @@ -126,11 +128,11 @@ def _prop_crosswalk(self, par_list: list[Param]) -> list[Param]:
for par in par_list:
what = par.p_type
if what in self._config.prop_type_crosswalk:
if "vector" in what:
if "vector<" in what:
params.append(
Param("int", f"{par.name}Len",
f"Length of vector reserved for {par.name}.", "in"))
elif what.endswith("*const"):
elif what.endswith("* const") or what.endswith("double*"):
direction = "in" if what.startswith("const") else "out"
params.append(
Param("int", f"{par.name}Len",
Expand All @@ -140,8 +142,18 @@ def _prop_crosswalk(self, par_list: list[Param]) -> list[Param]:
elif "shared_ptr" in what:
handle = self._handle_crosswalk(
what, self._config.prop_type_crosswalk, [])
description = f"Integer handle to {handle} object. {par.description}"
params.append(Param("int", par.name, description, par.direction))
if "vector<" in what:
params.append(
Param("int", f"{par.name}Len",
f"Length of array reserved for {par.name}.", "in"))
description = f"Memory holding {handle} objects. "
description += par.description
params.append(Param("const int*", par.name, description.strip()))
else:
description = f"Integer handle to {handle} object. "
description += par.description
params.append(
Param("int", par.name, description.strip(), par.direction))
else:
_LOGGER.critical(f"Failed crosswalk for argument type {what!r}.")
sys.exit(1)
Expand Down Expand Up @@ -211,7 +223,17 @@ def shared_object(cxx_type):
if check_array:
# Need to handle cross-walked parameter with length information
c_prev = c_args[c_ix-1].name
if "vector" in cxx_type:
if "vector<shared_ptr" in cxx_type:
# Example: vector<shared_ptr<Solution>>
cxx_type = cxx_type.lstrip("const ").rstrip("&")
lines.extend([
f"{cxx_type} {c_name}_;",
f"for (int i = 0; i < {c_prev}; i++) {{",
f" {c_name}_.push_back({base}Cabinet::at({c_name}[i]));",
"}",
])
args.append(f"{c_name}_")
elif "vector" in cxx_type:
# Example: vector<double> par_(par, par + parLen);
cxx_type = cxx_type.rstrip("&")
lines.append(
Expand Down Expand Up @@ -303,7 +325,7 @@ def _scaffold_body(self, c_func: CFunc, recipe: Recipe) -> tuple[str, set[str]]:
template = loader.from_string(self._templates["clib-method"])

elif recipe.what == "reserved":
args["cabinets"] = [kk for kk in self._config.includes.keys() if kk]
args["cabinets"] = [kk for kk in self._clib_bases if kk]
template = loader.from_string(
self._templates[f"clib-reserved-{recipe.name}-cpp"])

Expand Down Expand Up @@ -393,7 +415,9 @@ def merge_params(implements, cxx_func: CFunc) -> tuple[list[Param], int]:
recipe.what = "getter"
elif "void" in cxx_func.ret_type and cxx_arglen == 1:
p_type = cxx_func.arglist[0].p_type
if "*" in p_type and not p_type.startswith("const"):
if cxx_func.name.startswith("get"):
recipe.what = "getter"
elif "*" in p_type and not p_type.startswith("const"):
recipe.what = "getter" # getter assigns to existing array
else:
recipe.what = "setter"
Expand Down Expand Up @@ -483,7 +507,7 @@ def _write_implementation(self, headers: HeaderFile) -> None:

if not headers.base:
# main CLib file receives references to all cabinets
other = [kk for kk in self._config.includes.keys() if kk]
other = [kk for kk in self._clib_bases if kk]
includes = []
for obj in [headers.base] + list(other):
includes += self._config.includes[obj]
Expand All @@ -504,13 +528,17 @@ def _write_implementation(self, headers: HeaderFile) -> None:

def resolve_tags(self, headers_files: list[HeaderFile], quiet: bool=True):
"""Resolve doxygen tags."""
def get_bases() -> list[str]:
def get_bases() -> tuple[list[str], list[str]]:
bases = set()
classes = set()
for headers in headers_files:
bases |= {headers.base}
for recipe in headers.recipes:
bases |= set([recipe.base] + recipe.parents)
return list(bases)
self._doxygen_tags = TagFileParser(get_bases())
classes |= set([recipe.base] + recipe.parents + recipe.derived)
return sorted(bases), sorted(classes)

self._clib_bases, classes = get_bases()
self._doxygen_tags = TagFileParser(classes)

for headers in headers_files:
if not quiet:
Expand Down
5 changes: 3 additions & 2 deletions interfaces/sourcegen/sourcegen/clib/_Config.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,9 @@ class Config:
"size_t": "int",
"double": "double",
"const double": "double",
"double *const": "double*",
"const double *const": "const double*",
"double*": "double*",
"double* const": "double*",
"const double* const": "const double*",
"const string&": "const char*",
"shared_ptr<T>": "int",
"const shared_ptr<T>": "int",
Expand Down
4 changes: 3 additions & 1 deletion interfaces/sourcegen/sourcegen/clib/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,16 @@ ignore_files: []

# Ignore these specific functions:
ignore_funcs:
ctsol_auto.yaml: [newInterface, setTransport]
ctsol_auto.yaml: [setTransport]

# Cabinets with associated includes
includes:
"":
- cantera/base/global.h
Solution:
- cantera/base/Solution.h
Interface:
- cantera/base/Interface.h
ThermoPhase:
- cantera/thermo/ThermoFactory.h
Kinetics:
Expand Down

0 comments on commit 4a7f97f

Please sign in to comment.