Add code generation for array

This commit is contained in:
2025-05-04 23:26:03 +01:00
parent f444911452
commit 12f083edb0
18 changed files with 4466 additions and 1 deletions

355
codegen/array/make_array.py Normal file
View File

@@ -0,0 +1,355 @@
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 / "primitives" / "strings" / "str8" / "str8.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",
),
}
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)
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),
],
)
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,
),
)
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),
],
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),
],
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,
),
)
pop_func = CFunc(
name=f"wapp_{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,
),
)
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,
),
)
alloc_capacity_func = CFunc(
name=f"wapp_{type_string_lower}_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),
],
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),
)
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),
],
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),
)
header.decl_types.extend(array_data.hdr_decl_types)
header.macros.extend([stack_array_macro, stack_capacity_array_macro])
header.types.extend([array])
header.funcs.extend([
get_func,
set_func,
append_capped_func,
extend_capped_func,
clear_func,
pop_func,
copy_capped_func,
alloc_capacity_func,
append_alloc_func,
extend_alloc_func,
copy_alloc_func,
])
source.decl_types.extend(array_data.src_decl_types)
source.funcs = header.funcs
header.save(out_dir)
source.save(out_dir)

View File

@@ -0,0 +1,18 @@
u64 allocation_size = sizeof({ArrayType}) + sizeof({T}) * capacity;
{ArrayType} *array = NULL;
if (!allocator) {{
goto RETURN_{Tupper}_ARRAY_ALLOC;
}}
array = wapp_mem_allocator_alloc(allocator, allocation_size);
if (!array) {{
goto RETURN_{Tupper}_ARRAY_ALLOC;
}}
array->items = ({T} *)((u8 *)array + sizeof({ArrayType}));
array->count = 0;
array->capacity = capacity;
RETURN_{Tupper}_ARRAY_ALLOC:
return array;

View File

@@ -0,0 +1,20 @@
{ArrayType} *output = array;
if (!allocator || !array) {{
goto RETURN_{Tupper}_ARRAY_APPEND_ALLOC;
}}
if (array->count >= array->capacity) {{
u64 new_capacity = wapp_misc_utils_u64_round_up_pow2(array->capacity * 2);
output = wapp_{Tlower}_array_alloc_capacity(allocator, new_capacity);
if (!output) {{
output = array;
goto RETURN_{Tupper}_ARRAY_APPEND_ALLOC;
}}
wapp_{Tlower}_array_copy_capped(array, output);
}}
wapp_{Tlower}_array_append_capped(output, item);
RETURN_{Tupper}_ARRAY_APPEND_ALLOC:
return output;

View File

@@ -0,0 +1,5 @@
if (!array || array->count >= array->capacity) {{
return;
}}
array->items[(array->count)++] = item;

View File

@@ -0,0 +1,5 @@
if (!array || index >= array->count) {{
return NULL;
}}
return &(array->items[index]);

View File

@@ -0,0 +1,5 @@
if (!array || array->count == 0) {{
return ({T}){{0}};
}}
return array->items[--(array->count)];

View File

@@ -0,0 +1,5 @@
if (!array || index >= array->count) {{
return;
}}
array->items[index] = item;

View File

@@ -0,0 +1,5 @@
if (!array) {{
return;
}}
array->count = 0;

View File

@@ -0,0 +1,20 @@
{ArrayType} *output = dst;
if (!allocator || !src || !dst) {{
goto RETURN_{Tupper}_ARRAY_COPY_ALLOC;
}}
if (src->count >= dst->capacity) {{
u64 new_capacity = wapp_misc_utils_u64_round_up_pow2(dst->capacity * 2);
output = wapp_{Tlower}_array_alloc_capacity(allocator, new_capacity);
if (!output) {{
output = dst;
goto RETURN_{Tupper}_ARRAY_COPY_ALLOC;
}}
}}
wapp_{Tlower}_array_clear(output);
wapp_{Tlower}_array_copy_capped(src, output);
RETURN_{Tupper}_ARRAY_COPY_ALLOC:
return output;

View File

@@ -0,0 +1,16 @@
if (!src || !dst) {{
return;
}}
wapp_{Tlower}_array_clear(dst);
{T} *item;
u64 to_copy = src->count < dst->capacity ? src->count : dst->capacity;
for (u64 i = 0; i < to_copy; ++i) {{
item = wapp_{Tlower}_array_get(src, i);
if (!item) {{
continue;
}}
wapp_{Tlower}_array_append_capped(dst, *item);
}}

View File

@@ -0,0 +1,21 @@
{ArrayType} *output = array;
if (!allocator || !array || !other) {{
goto RETURN_{Tupper}_ARRAY_EXTEND_ALLOC;
}}
u64 remaining_capacity = array->capacity - array->count;
if (other->count >= remaining_capacity) {{
u64 new_capacity = wapp_misc_utils_u64_round_up_pow2(array->capacity * 2);
output = wapp_{Tlower}_array_alloc_capacity(allocator, new_capacity);
if (!output) {{
output = array;
goto RETURN_{Tupper}_ARRAY_EXTEND_ALLOC;
}}
wapp_{Tlower}_array_copy_capped(array, output);
}}
wapp_{Tlower}_array_extend_capped(output, other);
RETURN_{Tupper}_ARRAY_EXTEND_ALLOC:
return output;

View File

@@ -0,0 +1,19 @@
if (!array || !other) {{
return;
}}
u64 remaining_capacity = array->capacity - array->count;
if (other->count >= remaining_capacity) {{
return;
}}
{T} *item;
u64 items_to_add = other->count;
for (u64 i = 0; i < items_to_add; ++i) {{
item = wapp_{Tlower}_array_get(other, i);
if (!item) {{
continue;
}}
wapp_{Tlower}_array_append_capped(array, *item);
}}

View File

@@ -0,0 +1,5 @@
(({ArrayType}){{ \
.items = ({T}[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count({T}, __VA_ARGS__) * 2)]){{__VA_ARGS__}}, \
.count = wapp_misc_utils_va_args_count({T}, __VA_ARGS__), \
.capacity = wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count({T}, __VA_ARGS__) * 2) \
}})

View File

@@ -0,0 +1 @@
(({ArrayType}){{.items = ({T}[CAPACITY]){{0}}, .count = 0, .capacity = CAPACITY}})