Init new repository

This commit is contained in:
Krzosa Karol
2024-04-13 15:29:53 +02:00
commit 5a2e3dcec4
335 changed files with 61571 additions and 0 deletions

View File

@@ -0,0 +1,173 @@
bool add_dynamic_array_macro() {
LC_Lang *lang = LC_LangAlloc();
lang->use_colored_terminal_output = UseColoredIO;
lang->breakpoint_on_error = BreakpointOnError;
LC_LangBegin(lang);
LC_RegisterPackageDir("../pkgs");
LC_RegisterPackageDir("../examples");
LC_Intern name = LC_ILit("add_dynamic_array_macro");
LC_ParsePackagesUsingRegistry(name);
if (L->errors) {
LC_LangEnd(lang);
return false;
}
Array<LC_Intern> array_of_to_gen = {MA_GetAllocator(L->arena)};
LC_Intern init_array = LC_ILit("init_array");
LC_AST *init_array_ast = LC_ParseStmtf("{ init_array_base(REF, SIZE, sizeof(REF.data[0])); }");
LC_AST *init_array_add_ast = LC_ParseStmtf("{ REF.data[REF.len] = ITEM; REF.len += 1; }");
LC_Intern add = LC_ILit("add");
LC_AST *add_ast = LC_ParseStmtf(
"{"
" try_growing_array(REF, sizeof(REF.data[0]));"
" REF.data[REF.len] = ITEM;"
" REF.len += 1;"
"}");
LC_Intern ITEM = LC_ILit("ITEM");
LC_Intern REF = LC_ILit("REF");
LC_AST *package = LC_GetPackageByName(name);
LC_AST *first_ast = (LC_AST *)L->ast_arena->memory.data;
for (int i = 0; i < L->ast_count; i += 1) {
LC_AST *it = first_ast + i;
// Detect and save to array every unique use of 'ArrayOfT'
if (it->kind == LC_ASTKind_TypespecIdent) {
S8_String name = S8_MakeFromChar((char *)it->eident.name);
if (S8_StartsWith(name, "ArrayOf")) {
S8_String s8 = S8_Skip(name, S8_Lit("ArrayOf").len);
LC_Intern type = LC_InternStrLen(s8.str, (int)s8.len);
bool is_unique = true;
For2(in_array, array_of_to_gen) {
if (in_array == type) {
is_unique = false;
break;
}
}
if (is_unique) array_of_to_gen.add(type);
}
}
if (it->kind == LC_ASTKind_StmtExpr && it->sexpr.expr->kind == LC_ASTKind_ExprCall) {
LC_AST *name = it->sexpr.expr->ecompo.name;
LC_AST *call = it->sexpr.expr;
if (name->kind != LC_ASTKind_ExprIdent) {
continue;
}
if (name->eident.name == add) {
if (call->ecompo.size != 2) {
LC_ReportASTError(call, "wrong argument count in macro call");
continue;
}
LC_AST *first_item = call->ecompo.first;
LC_AST *arr_ref = first_item->ecompo_item.expr;
LC_AST *item = first_item->next->ecompo_item.expr;
LC_AST *macro = LC_CopyAST(L->arena, add_ast);
LC_ASTArray array = LC_FlattenAST(L->arena, macro);
for (int m_i = 0; m_i < array.len; m_i += 1) {
LC_AST *m_it = array.data[m_i];
if (m_it->kind == LC_ASTKind_ExprIdent) {
if (m_it->eident.name == ITEM) {
*m_it = *LC_CopyAST(L->arena, item);
} else if (m_it->eident.name == REF) {
*m_it = *LC_CopyAST(L->arena, arr_ref);
}
}
m_it->pos = it->pos;
}
macro->next = it->next;
macro->prev = it->prev;
*it = *macro;
}
if (name->eident.name == init_array) {
if (call->ecompo.size != 2) {
LC_ReportASTError(call, "wrong argument count in macro call");
continue;
}
LC_AST *first_item = call->ecompo.first;
LC_AST *arr_ref = first_item->ecompo_item.expr;
LC_AST *item = first_item->next->ecompo_item.expr;
if (item->kind != LC_ASTKind_ExprCompound) {
LC_ReportASTError(item, "expected compound");
continue;
}
LC_AST *macro = LC_CopyAST(L->arena, init_array_ast);
LC_ASTArray array = LC_FlattenAST(L->arena, macro);
for (int m_i = 0; m_i < array.len; m_i += 1) {
LC_AST *m_it = array.data[m_i];
if (m_it->kind != LC_ASTKind_ExprIdent) continue;
if (m_it->eident.name == LC_ILit("SIZE")) {
// This is a bit dangerous here because through
// this call we are bumping L->ast_count += 1
*m_it = *LC_CreateAST(item->pos, LC_ASTKind_ExprInt);
m_it->eatom.i = LC_Bigint_u64(item->ecompo.size);
} else if (m_it->eident.name == REF) {
*m_it = *LC_CopyAST(L->arena, arr_ref);
}
m_it->pos = it->pos;
}
LC_ASTFor(item_it, item->ecompo.first) {
LC_AST *init_item = LC_CopyAST(L->arena, init_array_add_ast);
LC_ASTArray array = LC_FlattenAST(L->arena, init_item);
for (int m_i = 0; m_i < array.len; m_i += 1) {
LC_AST *m_it = array.data[m_i];
if (m_it->kind == LC_ASTKind_ExprIdent) {
if (m_it->eident.name == ITEM) {
*m_it = *LC_CopyAST(L->arena, item_it->ecompo_item.expr);
} else if (m_it->eident.name == REF) {
*m_it = *LC_CopyAST(L->arena, arr_ref);
}
}
m_it->pos = name->pos;
}
LC_DLLAdd(macro->sblock.first, macro->sblock.last, init_item);
}
macro->next = it->next;
macro->prev = it->prev;
*it = *macro;
}
}
}
// @todo: take package into consideration, my current idea is to have a shared package
// that is going to be imported into every other package, for now we use only the current package
For(array_of_to_gen) {
LC_AST *ast = LC_ParseDeclf("ArrayOf%s :: struct { data: *%s; len: int; cap: int; }", (char *)it, (char *)it);
LC_AST *file = package->apackage.ffile;
LC_DLLAdd(file->afile.fdecl, file->afile.ldecl, ast);
}
LC_OrderAndResolveTopLevelDecls(name);
LC_ResolveAllProcBodies();
if (L->errors) {
LC_LangEnd(lang);
return false;
}
LC_String code = LC_GenerateUnityBuild(L->ordered_packages);
OS_MakeDir("examples/add_dynamic_array_macro");
OS_WriteFile("examples/add_dynamic_array_macro/add_dynamic_array_macro.c", code);
return true;
}

View File

@@ -0,0 +1,64 @@
import "libc";
try_growing_array :: proc(arrp: *void, element_size: size_t) {
arr: *ArrayOfvoid = arrp;
if (arr.len + 1 > arr.cap) {
cap := arr.cap * 2;
if (cap == 0) cap = 16;
arr.data = realloc(arr.data, element_size * :size_t(cap));
arr.cap = cap;
}
}
init_array_base :: proc(arrp: *void, size: int, element_size: size_t) {
arr: *ArrayOfvoid = arrp;
arr.data = malloc(element_size * :size_t(size * 2));
arr.len = size * 2;
}
main :: proc(): int {
{
arr: ArrayOfint;
init_array(&arr, {0, 1, 2, 3, 4, 6, 7, 9, 10});
for i := 0; i < 10; i += 1 {
assert(arr.data[i] == i);
}
for it := &arr.data[0]; it < &arr.data[arr.len]; it = &it[1] {
}
}
{
arr: ArrayOfint;
for i := 0; i < 128; i += 1 {
add(&arr, i);
}
for i := 0; i < 128; i += 1 {
assert(arr.data[i] == i);
}
}
{
arr: ArrayOffloat;
for i: float = 0; i < 128; i += 1 {
add(&arr, i);
}
for i := 0; i < 128; i += 1 {
i0 := :int(arr.data[i]);
assert(i0 == i);
}
}
return 0;
}