from pathlib import Path from dataclasses import dataclass, field from typing import List, Dict from codegen.constants import WAPP_SRC_ROOT from codegen.utils import load_func_body_from_file, convert_to_relative from codegen.datatypes import ( CDataType, CMacro, CStruct, CFunc, CHeader, CSource, CArg, CType, CPointer, CPointerType, CQualifier, CInclude, get_datatype_string, ) @dataclass class ArrayData: array_typename: str hdr_decl_types: List[CStruct] = field(default_factory=list) src_decl_types: List[CStruct] = field(default_factory=list) def make_array(user_datatypes: Dict[CDataType, ArrayData] = {}): def __format_func_body( filename: Path, type_string: str, type_string_upper: str, type_string_lower: str, array_typename: str ): return load_func_body_from_file(filename).format( T=type_string, ArrayType=array_typename, Tupper=type_string_upper, Tlower=type_string_lower, ) out_dir = WAPP_SRC_ROOT / "primitives" / "array" out_dir.mkdir(parents=True, exist_ok=True) common_includes: List[CInclude] = [ CInclude(header="stdbool.h"), CInclude( header=str(convert_to_relative(WAPP_SRC_ROOT / "primitives" / "mem_allocator" / "mem_allocator.h", out_dir)).replace("\\", "/"), local=True, ), CInclude( header=str(convert_to_relative(WAPP_SRC_ROOT / "common" / "misc" / "misc_utils.h", out_dir)).replace("\\", "/"), local=True, ), ] common_decl_types: List[CStruct] = [] datatypes: dict[CDataType, ArrayData] = { "Str8": ArrayData( array_typename="Str8Array", hdr_decl_types=[ CStruct(name="str8", cargs=[], typedef_name="Str8"), ], ), } for _type in CType: if _type == CType.VOID: datatypes["void *"] = ArrayData( array_typename="VoidPArray", ) continue elif _type == CType.BOOL: datatypes[_type.value] = ArrayData( array_typename="BoolArray", ) continue type_title = _type.value.title() datatypes[_type.value] = ArrayData( array_typename=f"{type_title}Array", ) datatypes.update(user_datatypes) snippets_dir = Path(__file__).parent / "snippets" header = CHeader( name="array", 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) generic_funcs = [] for _type, array_data in datatypes.items(): type_string = get_datatype_string(_type) clean_type_string = type_string.replace(" ", "").replace("*", "_ptr") type_string_upper = clean_type_string.upper() type_string_lower = clean_type_string.lower() array = CStruct( name=array_data.array_typename, cargs=[ CArg(name="items", _type=type_string, pointer=CPointer(_type=CPointerType.SINGLE)), CArg(name="count", _type=CType.U64), CArg(name="capacity", _type=CType.U64), CArg(name="item_size", _type=CType.U64), ], ) if isinstance(_type, str) and _type == "void *": alloc_capacity_func = CFunc( name=f"_array_alloc_capacity", ret_type=array, args=[ CArg(name="allocator", _type="Allocator", pointer=CPointer(CPointerType.SINGLE), qualifier=CQualifier.CONST), CArg(name="capacity", _type=CType.U64), CArg(name="item_size", _type=CType.U64), ], body=__format_func_body( filename=snippets_dir / "alloc_capacity", type_string=type_string, type_string_upper=type_string_upper, type_string_lower=type_string_lower, array_typename=array_data.array_typename, ), pointer=CPointer(CPointerType.SINGLE), ) generic_funcs.append(alloc_capacity_func) stack_array_macro = CMacro( name=f"wapp_{type_string_lower}_array(...)", value=__format_func_body( filename=snippets_dir / "stack_array", type_string=type_string, type_string_upper=type_string_upper, type_string_lower=type_string_lower, array_typename=array_data.array_typename, ), ) stack_capacity_array_macro = CMacro( name=f"wapp_{type_string_lower}_array_with_capacity(CAPACITY)", value=__format_func_body( filename=snippets_dir / "stack_capacity_array", type_string=type_string, type_string_upper=type_string_upper, type_string_lower=type_string_lower, array_typename=array_data.array_typename, ), ) alloc_capacity_array_macro = CMacro( name=f"wapp_{type_string_lower}_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY)", value=__format_func_body( filename=snippets_dir / "alloc_capacity_macro", type_string=type_string, type_string_upper=type_string_upper, type_string_lower=type_string_lower, array_typename=array_data.array_typename, ), ) array_pop_macro = CMacro( name=f"wapp_{type_string_lower}_array_pop(ARRAY_PTR)", value=__format_func_body( filename=snippets_dir / "array_pop_macro", type_string=type_string, type_string_upper=type_string_upper, type_string_lower=type_string_lower, array_typename=array_data.array_typename, ), ) get_func = CFunc( name=f"wapp_{type_string_lower}_array_get", ret_type=type_string, args=[ CArg(name="array", _type=array, pointer=CPointer(CPointerType.SINGLE), qualifier=CQualifier.CONST), CArg(name="index", _type=CType.U64), ], body=__format_func_body( filename=snippets_dir / "array_get", type_string=type_string, type_string_upper=type_string_upper, type_string_lower=type_string_lower, array_typename=array_data.array_typename, ), pointer=CPointer(CPointerType.SINGLE), ) set_func = CFunc( name=f"wapp_{type_string_lower}_array_set", ret_type=CType.VOID, args=[ CArg(name="array", _type=array, pointer=CPointer(CPointerType.SINGLE)), CArg(name="index", _type=CType.U64), CArg(name="item", _type=type_string, pointer=CPointer(CPointerType.SINGLE)), ], body=__format_func_body( filename=snippets_dir / "array_set", type_string=type_string, type_string_upper=type_string_upper, type_string_lower=type_string_lower, array_typename=array_data.array_typename, ), ) append_capped_func = CFunc( name=f"wapp_{type_string_lower}_array_append_capped", ret_type=CType.VOID, args=[ CArg(name="array", _type=array, pointer=CPointer(CPointerType.SINGLE)), CArg(name="item", _type=type_string, pointer=CPointer(CPointerType.SINGLE)), ], body=__format_func_body( filename=snippets_dir / "append_capped", type_string=type_string, type_string_upper=type_string_upper, type_string_lower=type_string_lower, array_typename=array_data.array_typename, ), ) extend_capped_func = CFunc( name=f"wapp_{type_string_lower}_array_extend_capped", ret_type=CType.VOID, args=[ CArg(name="array", _type=array, pointer=CPointer(CPointerType.SINGLE)), CArg(name="other", _type=array, pointer=CPointer(CPointerType.SINGLE), qualifier=CQualifier.CONST), ], body=__format_func_body( filename=snippets_dir / "extend_capped", type_string=type_string, type_string_upper=type_string_upper, type_string_lower=type_string_lower, array_typename=array_data.array_typename, ), ) clear_func = CFunc( name=f"wapp_{type_string_lower}_array_clear", ret_type=CType.VOID, args=[ CArg(name="array", _type=array, pointer=CPointer(CPointerType.SINGLE)), ], body=__format_func_body( filename=snippets_dir / "clear", type_string=type_string, type_string_upper=type_string_upper, type_string_lower=type_string_lower, array_typename=array_data.array_typename, ), ) copy_capped_func = CFunc( name=f"wapp_{type_string_lower}_array_copy_capped", ret_type=CType.VOID, args=[ CArg(name="src", _type=array, pointer=CPointer(CPointerType.SINGLE), qualifier=CQualifier.CONST), CArg(name="dst", _type=array, pointer=CPointer(CPointerType.SINGLE)), ], body=__format_func_body( filename=snippets_dir / "copy_capped", type_string=type_string, type_string_upper=type_string_upper, type_string_lower=type_string_lower, array_typename=array_data.array_typename, ), ) append_alloc_func = CFunc( name=f"wapp_{type_string_lower}_array_append_alloc", ret_type=array, args=[ CArg(name="allocator", _type="Allocator", pointer=CPointer(CPointerType.SINGLE), qualifier=CQualifier.CONST), CArg(name="array", _type=array, pointer=CPointer(CPointerType.SINGLE)), CArg(name="item", _type=type_string, pointer=CPointer(CPointerType.SINGLE)), ], body=__format_func_body( filename=snippets_dir / "append_alloc", type_string=type_string, type_string_upper=type_string_upper, type_string_lower=type_string_lower, array_typename=array_data.array_typename, ), pointer=CPointer(CPointerType.SINGLE), ) extend_alloc_func = CFunc( name=f"wapp_{type_string_lower}_array_extend_alloc", ret_type=array, args=[ CArg(name="allocator", _type="Allocator", pointer=CPointer(CPointerType.SINGLE), qualifier=CQualifier.CONST), CArg(name="array", _type=array, pointer=CPointer(CPointerType.SINGLE)), CArg(name="other", _type=array, pointer=CPointer(CPointerType.SINGLE), qualifier=CQualifier.CONST), ], body=__format_func_body( filename=snippets_dir / "extend_alloc", type_string=type_string, type_string_upper=type_string_upper, type_string_lower=type_string_lower, array_typename=array_data.array_typename, ), pointer=CPointer(CPointerType.SINGLE), ) copy_alloc_func = CFunc( name=f"wapp_{type_string_lower}_array_copy_alloc", ret_type=array, args=[ CArg(name="allocator", _type="Allocator", pointer=CPointer(CPointerType.SINGLE), qualifier=CQualifier.CONST), CArg(name="src", _type=array, pointer=CPointer(CPointerType.SINGLE), qualifier=CQualifier.CONST), CArg(name="dst", _type=array, pointer=CPointer(CPointerType.SINGLE)), ], body=__format_func_body( filename=snippets_dir / "copy_alloc", type_string=type_string, type_string_upper=type_string_upper, type_string_lower=type_string_lower, array_typename=array_data.array_typename, ), pointer=CPointer(CPointerType.SINGLE), ) pop_func = CFunc( name=f"_{type_string_lower}_array_pop", ret_type=type_string, args=[ CArg(name="array", _type=array, pointer=CPointer(CPointerType.SINGLE)), ], body=__format_func_body( filename=snippets_dir / "array_pop", type_string=type_string, type_string_upper=type_string_upper, type_string_lower=type_string_lower, array_typename=array_data.array_typename, ), pointer=CPointer(CPointerType.SINGLE), ) header.decl_types.extend(array_data.hdr_decl_types) header.macros.extend([ stack_array_macro, stack_capacity_array_macro, alloc_capacity_array_macro, array_pop_macro, ]) header.types.extend([array]) header.funcs.extend([ get_func, set_func, append_capped_func, extend_capped_func, clear_func, copy_capped_func, append_alloc_func, extend_alloc_func, copy_alloc_func, pop_func, ]) source.decl_types.extend(array_data.src_decl_types) source.funcs = header.funcs header.funcs.extend(generic_funcs) header.save(out_dir) source.save(out_dir)