Auto generate the boilerplate code to convert python opts to c opts

This commit is contained in:
Kovid Goyal
2021-06-03 18:30:13 +05:30
parent 4ab299d0af
commit 2e71429b03
8 changed files with 1057 additions and 100 deletions

View File

@@ -323,12 +323,59 @@ def generate_class(defn: Definition, loc: str) -> Tuple[str, str]:
return class_def, '\n'.join(preamble + ['', ''] + tc_lines)
def generate_c_conversion(loc: str, ctypes: List[Option]) -> str:
lines: List[str] = []
basic_converters = {
'int': 'PyLong_AsLong', 'uint': 'PyLong_AsUnsignedLong', 'bool': 'PyObject_IsTrue',
'float': 'PyFloat_AsFloat', 'double': 'PyFloat_AsDouble',
'time': 'parse_s_double_to_monotonic_t', 'time-ms': 'parse_ms_long_to_monotonic_t'
}
for opt in ctypes:
lines.append('')
lines.append(f'static void\nconvert_from_python_{opt.name}(PyObject *val, Options *opts) ''{')
is_special = opt.ctype.startswith('!')
if is_special:
func = opt.ctype[1:]
lines.append(f' {func}(val, opts);')
else:
func = basic_converters.get(opt.ctype, opt.ctype)
lines.append(f' opts->{opt.name} = {func}(val);')
lines.append('}')
lines.append('')
lines.append(f'static void\nconvert_from_opts_{opt.name}(PyObject *py_opts, Options *opts) ''{')
lines.append(f' PyObject *ret = PyObject_GetAttrString(py_opts, "{opt.name}");')
lines.append(' if (ret == NULL) return;')
lines.append(f' convert_from_python_{opt.name}(ret, opts);')
lines.append(' Py_DECREF(ret);')
lines.append('}')
lines.append('')
lines.append('static bool\nconvert_opts_from_python_opts(PyObject *py_opts, Options *opts) ''{')
for opt in ctypes:
lines.append(f' convert_from_opts_{opt.name}(py_opts, opts);')
lines.append(' if (PyErr_Occurred()) return false;')
lines.append(' return true;')
lines.append('}')
preamble = ['// generated by gen-config.py DO NOT edit', '// vim:fileencoding=utf-8', '#pragma once', '#include "to-c.h"']
return '\n'.join(preamble + ['', ''] + lines)
def write_output(loc: str, defn: Definition) -> None:
cls, tc = generate_class(defn, loc)
with open(os.path.join(*loc.split('.'), 'options', 'types.py'), 'w') as f:
f.write(cls + '\n')
with open(os.path.join(*loc.split('.'), 'options', 'parse.py'), 'w') as f:
f.write(tc + '\n')
ctypes = []
for opt in defn.root_group.iter_all_non_groups():
if isinstance(opt, Option) and opt.ctype:
ctypes.append(opt)
if ctypes:
c = generate_c_conversion(loc, ctypes)
with open(os.path.join(*loc.split('.'), 'options', 'to-c-generated.h'), 'w') as f:
f.write(c + '\n')
def main() -> None: