from pathlib import Path from dataclasses import dataclass, field from codegen.constants import WAPP_SRC_ROOT from codegen.utils import load_func_body_from_file from codegen.datatypes import ( CDataType, CMacro, CStruct, CFunc, CHeader, CSource, CArg, CType, CPointer, CPointerType, CQualifier, CInclude, get_datatype_string, ) @dataclass class DblListData: node_typename: str list_typename: str hdr_decl_types: list[CStruct] = field(default_factory=list) src_decl_types: list[CStruct] = field(default_factory=list) def make_dbl_list(user_datatypes: dict[CDataType, DblListData] = {}): def __format_func_body(filename: Path, type_string: str, node_typename: str, list_typename: str): return load_func_body_from_file(filename).format( T=type_string, NodeType=node_typename, ListType=list_typename, Tupper=type_string.upper(), Tlower=type_string.lower(), ) out_dir = WAPP_SRC_ROOT / "containers" / "dbl_list" out_dir.mkdir(parents=True, exist_ok=True) common_local_include_files = [ (WAPP_SRC_ROOT / "common" / "aliases" / "aliases.h") ] common_includes: list[CInclude] = [] for local_file in common_local_include_files: common_includes.append( CInclude( header=str(local_file.relative_to(out_dir, walk_up=True)), local=True, ) ) common_decl_types: list[CStruct] = [] datatypes: dict[CDataType, DblListData] = { "Str8": DblListData( node_typename="Str8Node", list_typename="Str8List", hdr_decl_types=[ CStruct(name="str8", cargs=[], typedef_name="Str8"), ], ), } datatypes.update(user_datatypes) snippets_dir = Path(__file__).parent / "snippets" header = CHeader( name="dbl_list", decl_types=common_decl_types, includes=[], types=[], funcs=[] ) source = CSource( name=header.name, decl_types=common_decl_types, includes=[CInclude(header, local=True, same_dir=True), CInclude(header="stddef.h")], internal_funcs=[], funcs=header.funcs ) if len(common_includes) > 0: header.includes.extend(common_includes) source.includes.extend(common_includes) for _type, dbl_list_data in datatypes.items(): type_string = get_datatype_string(_type) node = CStruct( name=f"{type_string.title()}Node", cargs=[ CArg(name="item", _type=type_string, pointer=CPointer(_type=CPointerType.SINGLE)), ], ) node.cargs.extend([ CArg(name="prev", _type=node, pointer=CPointer(_type=CPointerType.SINGLE)), CArg(name="next", _type=node, pointer=CPointer(_type=CPointerType.SINGLE)), ]) dl_list = CStruct( name=f"{type_string.title()}List", cargs=[ CArg(name="first", _type=node, pointer=CPointer(_type=CPointerType.SINGLE)), CArg(name="last", _type=node, pointer=CPointer(_type=CPointerType.SINGLE)), CArg(name="node_count", _type=CType.U64), ], ) node_macro = CMacro( name=f"wapp_{type_string.lower()}_list_node(ITEM_PTR)", value=__format_func_body( filename=snippets_dir / "list_node", type_string=type_string, node_typename=dbl_list_data.node_typename, list_typename=dbl_list_data.list_typename ), ) get_func = CFunc( name=f"wapp_{type_string.lower()}_list_get", ret_type=node, args=[ CArg(name="list", _type=dl_list, pointer=CPointer(CPointerType.SINGLE), qualifier=CQualifier.CONST), CArg(name="index", _type=CType.U64), ], body=__format_func_body( filename=snippets_dir / "list_get", type_string=type_string, node_typename=dbl_list_data.node_typename, list_typename=dbl_list_data.list_typename ), pointer=CPointer(CPointerType.SINGLE), ) push_front_func = CFunc( name=f"wapp_{type_string.lower()}_list_push_front", ret_type=CType.VOID, args=[ CArg(name="list", _type=dl_list, pointer=CPointer(CPointerType.SINGLE)), CArg(name="node", _type=node, pointer=CPointer(CPointerType.SINGLE)), ], body=__format_func_body( filename=snippets_dir / "list_push_front", type_string=type_string, node_typename=dbl_list_data.node_typename, list_typename=dbl_list_data.list_typename ), ) push_back_func = CFunc( name=f"wapp_{type_string.lower()}_list_push_back", ret_type=CType.VOID, args=[ CArg(name="list", _type=dl_list, pointer=CPointer(CPointerType.SINGLE)), CArg(name="node", _type=node, pointer=CPointer(CPointerType.SINGLE)), ], body=__format_func_body( filename=snippets_dir / "list_push_back", type_string=type_string, node_typename=dbl_list_data.node_typename, list_typename=dbl_list_data.list_typename ), ) insert_func = CFunc( name=f"wapp_{type_string.lower()}_list_insert", ret_type=CType.VOID, args=[ CArg(name="list", _type=dl_list, pointer=CPointer(CPointerType.SINGLE)), CArg(name="node", _type=node, pointer=CPointer(CPointerType.SINGLE)), CArg(name="index", _type=CType.U64), ], body=__format_func_body( filename=snippets_dir / "list_insert", type_string=type_string, node_typename=dbl_list_data.node_typename, list_typename=dbl_list_data.list_typename ), ) pop_front_func = CFunc( name=f"wapp_{type_string.lower()}_list_pop_front", ret_type=node, args=[ CArg(name="list", _type=dl_list, pointer=CPointer(CPointerType.SINGLE)), ], body=__format_func_body( filename=snippets_dir / "list_pop_front", type_string=type_string, node_typename=dbl_list_data.node_typename, list_typename=dbl_list_data.list_typename ), pointer=CPointer(CPointerType.SINGLE), ) pop_back_func = CFunc( name=f"wapp_{type_string.lower()}_list_pop_back", ret_type=node, args=[ CArg(name="list", _type=dl_list, pointer=CPointer(CPointerType.SINGLE)), ], body=__format_func_body( filename=snippets_dir / "list_pop_back", type_string=type_string, node_typename=dbl_list_data.node_typename, list_typename=dbl_list_data.list_typename ), pointer=CPointer(CPointerType.SINGLE), ) remove_func = CFunc( name=f"wapp_{type_string.lower()}_list_remove", ret_type=node, args=[ CArg(name="list", _type=dl_list, pointer=CPointer(CPointerType.SINGLE)), CArg(name="index", _type=CType.U64), ], body=__format_func_body( filename=snippets_dir / "list_remove", type_string=type_string, node_typename=dbl_list_data.node_typename, list_typename=dbl_list_data.list_typename ), pointer=CPointer(CPointerType.SINGLE), ) empty_func = CFunc( name=f"wapp_{type_string.lower()}_list_empty", ret_type=CType.VOID, args=[ CArg(name="list", _type=dl_list, pointer=CPointer(CPointerType.SINGLE)), ], body=__format_func_body( filename=snippets_dir / "list_empty", type_string=type_string, node_typename=dbl_list_data.node_typename, list_typename=dbl_list_data.list_typename ), ) node_to_list_func = CFunc( name=f"{type_string.lower()}_node_to_list", ret_type=dl_list, args=[ CArg(name="node", _type=node, pointer=CPointer(CPointerType.SINGLE)), ], body=__format_func_body( filename=snippets_dir / "node_to_list", type_string=type_string, node_typename=dbl_list_data.node_typename, list_typename=dbl_list_data.list_typename ), qualifiers=[CQualifier.INTERNAL], ) header.decl_types.extend(dbl_list_data.hdr_decl_types) header.macros.append(node_macro) header.types.extend([node, dl_list]) header.funcs.extend([ get_func, push_front_func, push_back_func, insert_func, pop_front_func, pop_back_func, remove_func, empty_func, ]) source.decl_types.extend(dbl_list_data.src_decl_types) source.internal_funcs.append(node_to_list_func) source.funcs = header.funcs header.save(out_dir) source.save(out_dir)