From b10f3840dfce16d0195b187037b0b9efe3659ce7 Mon Sep 17 00:00:00 2001 From: Krzosa Karol Date: Sun, 2 Oct 2022 13:40:04 +0200 Subject: [PATCH] Single header mode sort of working --- base_string.cpp | 11 +++++ core_codegen_c_language.cpp | 95 +++++++++++++++++++++++++++---------- core_globals.cpp | 2 + core_main.cpp | 5 +- core_typechecking.cpp | 5 +- 5 files changed, 88 insertions(+), 30 deletions(-) diff --git a/base_string.cpp b/base_string.cpp index 322e207..cf64f6f 100644 --- a/base_string.cpp +++ b/base_string.cpp @@ -471,3 +471,14 @@ string_from_cstring(char *string){ return result; } +struct String_Replace { + String find; + String replace; +}; + +// function String +// string_replace(String string, Array pairs){ +// for(int i = 0; i < string.len; i++){ + +// } +// } \ No newline at end of file diff --git a/core_codegen_c_language.cpp b/core_codegen_c_language.cpp index ed391c0..07e3200 100644 --- a/core_codegen_c_language.cpp +++ b/core_codegen_c_language.cpp @@ -58,12 +58,13 @@ unique_name(Allocator *allocator, Ast *ast){ return result; } +global String prefixed_string_type; function const char * get_ctype_name_for_type(Ast_Type *type){ switch(type->kind){ case TYPE_VOID: return "void"; case TYPE_BOOL: return "bool"; - case TYPE_STRING: return "CORE_String"; + case TYPE_STRING: return (char *)prefixed_string_type.str; case TYPE_CHAR: return "char"; case TYPE_F32: return "float"; case TYPE_F64: return "double"; @@ -107,7 +108,7 @@ string_simple_decl_prefix(Allocator *a, Ast_Type *ast){ }break; case TYPE_STRUCT: { auto constant = (Ast_Decl *)ast->ast; - auto name = constant->name; + auto name = constant->unique_name; String string = string_fmt(a, "%Q ", name); String sc = {}; return string_fmt(a, "%Q%Q", sc, string); @@ -224,7 +225,7 @@ gen_value(Token *pos, Value a){ }break; case TYPE_STRING:{ int length = 0; - gen("(CORE_String){(uint8_t *)\""); + gen("(%QString){(uint8_t *)\"", symbol_prefix); for(int i = 0; i < a.intern_val.len; i++){ if(a.intern_val.str[i] == '\n'){length += 2; gen("\\n");} else if(a.intern_val.str[i] == '\r'){length += 2; gen("\\r");} @@ -525,8 +526,8 @@ gen_ast(Ast *ast){ switch(ast->kind){ CASE(RUNTIME_ASSERT, Builtin){ - if(node->assert_message.len == 0) gen("CORE_Assert"); - else gen("CORE_AssertMessage"); + if(node->assert_message.len == 0) gen("%QAssert", symbol_prefix); + else gen("%QAssertMessage", symbol_prefix); gen("("); gen_expr(node->expr); if(node->assert_message.len){ @@ -545,7 +546,7 @@ gen_ast(Ast *ast){ int i = 0; For(node->expr){ - genln("CORE_MemoryCopy(&%Q.m%d, ", var_name, i); + genln("%QMemoryCopy(&%Q.m%d, ", symbol_prefix, var_name, i); if(!is_array(it->resolved_type)) gen("&"); gen("("); gen_expr(it); @@ -624,7 +625,7 @@ gen_ast(Ast *ast){ if(node->is_array_traversal){ gen("for(int64_t _i%d = 0; _i%d < ", node->pos->line, node->pos->line); if(is_array(node->cond->resolved_type)){ - gen("CORE_BufferSize("); + gen("%QBufferSize(", symbol_prefix); gen_expr(node->cond); gen(")"); } else{ @@ -681,7 +682,7 @@ gen_ast(Ast *ast){ CASE(STRUCT, Decl){ gen("struct "); - gen("%Q{", node->name); + gen("%Q{", node->unique_name); global_indent++; is_inside_struct++; For(node->scope->decls){ @@ -695,12 +696,6 @@ gen_ast(Ast *ast){ BREAK(); } - CASE(TYPE, Decl){ - gen("// Type %Q = ", node->name); - gen_simple_decl(node->type_val); - BREAK(); - } - CASE(ENUM, Decl){ gen("/*enum %Q{", node->name); // @todo add typespec @@ -716,6 +711,7 @@ gen_ast(Ast *ast){ BREAK(); } + case AST_TYPE: CASE(CONST, Decl){unused(node);BREAK();} CASE(SWITCH, Switch){ @@ -761,7 +757,7 @@ gen_ast(Ast *ast){ int i = 0; For(node->vars){ - gen("CORE_MemoryCopy((void *)&%Q, (void *)&%Q.m%d, sizeof(%Q));", it->name, var_name, i++, it->name); + gen("%QMemoryCopy((void *)&%Q, (void *)&%Q.m%d, sizeof(%Q));", symbol_prefix, it->name, var_name, i++, it->name); } BREAK(); } @@ -782,26 +778,64 @@ function String compile_to_c_code(){ generating_time_begin = os_time(); + prefixed_string_type = string_fmt(pctx->perm, "%QString", symbol_prefix); + if(single_header_library_mode){ + gen(R"==( +/* + Do this: + #define %Q_IMPLEMENTATION + before you include this file in *one* C or C++ file to create the implementation. + + // i.e. it should look like this: + #include ... + #include ... + #include ... + #define %Q_IMPLEMENTATION + #include "%Q.h" + + You can #define %QAssert(x) to avoid using default assert + You can #define %QAssertMessage(x) to get more comprehensive error info + You can #define %QMemoryCopy(x) to avoid using default memory copy +*/ + )==", single_header_library_name, single_header_library_name, single_header_library_name, + symbol_prefix, symbol_prefix, symbol_prefix); + genln("#ifndef %Q_LIBRARY_HEADER ", single_header_library_name); + genln("#define %Q_LIBRARY_HEADER ", single_header_library_name); + } + gen(R"==( + #include #include -#define CORE_Assert(x) do{if(!(x))__debugbreak();}while(0) -#define CORE_AssertMessage(x,...) CORE_Assert(x) -#define CORE_BufferSize(x) (sizeof(x)/sizeof((x)[0])) -typedef struct CORE_String{ - uint8_t *str; - int64_t len; -}CORE_String; +#ifndef Assert +#define Assert(x) do{if(!(x))__debugbreak();}while(0) +#endif + +#ifndef AssertMessage +#define AssertMessage(x,...) Assert(x) +#endif + +#ifndef MemoryCopy +#define MemoryCopy MemoryCopy_ static void -CORE_MemoryCopy(void *dst, void *src, size_t size){ +MemoryCopy_(void *dst, void *src, size_t size){ uint8_t *d = (uint8_t*)dst; uint8_t *s = (uint8_t*)src; for(size_t i = 0; i < size; i++){ d[i] = s[i]; } } +#endif + +#define BufferSize(x) (sizeof(x)/sizeof((x)[0])) + +typedef struct String{ + uint8_t *str; + int64_t len; +}String; + )=="); @@ -809,7 +843,7 @@ CORE_MemoryCopy(void *dst, void *src, size_t size){ Iter(&pctx->ordered_decls){ auto i = it.item[0]; if(i->kind == AST_STRUCT){ - genln("typedef struct %Q %Q;", i->name, i->name); + genln("typedef struct %Q %Q;", i->unique_name, i->unique_name); } } @@ -912,7 +946,7 @@ CORE_MemoryCopy(void *dst, void *src, size_t size){ gen(".struct_member_count = %d, ", t->agg.members.len); gen(".struct_members = (Type_Info_Struct_Member[]){"); For_Named(t->agg.members, m){ - gen("{.name = (CORE_String){(uint8_t *)\"%Q\", %d}, .type = %d, .offset = %d}, ", m.name, m.name.len, m.type->type_id, m.offset); + gen("{.name = (%Q){(uint8_t *)\"%Q\", %d}, .type = %d, .offset = %d}, ", prefixed_string_type, m.name, m.name.len, m.type->type_id, m.offset); } gen("}"); @@ -927,6 +961,11 @@ CORE_MemoryCopy(void *dst, void *src, size_t size){ } + if(single_header_library_mode){ + genln("#endif"); + genln("#ifdef %Q_IMPLEMENTATION ", single_header_library_name); + } + // Generate actual code Iter(&pctx->ordered_decls){ if(it.index >= pctx->base_language_ordered_decl_len){ @@ -935,6 +974,12 @@ CORE_MemoryCopy(void *dst, void *src, size_t size){ } } + + if(single_header_library_mode){ + genln("#endif"); + } + + String string_result = string_flatten(pctx->perm, &pctx->gen); generating_time_end = os_time(); return string_result; diff --git a/core_globals.cpp b/core_globals.cpp index aa7442d..c00c580 100644 --- a/core_globals.cpp +++ b/core_globals.cpp @@ -1,6 +1,8 @@ global B32 emit_line_directives = true; global B32 emit_type_info = true; global String symbol_prefix = ""_s; +global B32 single_header_library_mode = false; +global String single_header_library_name = ""_s; diff --git a/core_main.cpp b/core_main.cpp index 126c056..db3e05b 100644 --- a/core_main.cpp +++ b/core_main.cpp @@ -293,9 +293,8 @@ int main(int argument_count, char **arguments){ test_string_builder(); test_intern_table(); - emit_line_directives = false; - emit_type_info = false; - symbol_prefix = "Ray_"_s; + // emit_line_directives = false; + // emit_type_info = false; if(argument_count > 1){ String program_name = string_from_cstring(arguments[1]); compile_file(program_name, COMPILE_PRINT_STATS); diff --git a/core_typechecking.cpp b/core_typechecking.cpp index 98bedc8..67b5f21 100644 --- a/core_typechecking.cpp +++ b/core_typechecking.cpp @@ -335,6 +335,7 @@ type_struct_complete(Ast_Type *type, Ast_Decl *node){ type->padding = type->size - members_size; type->agg.members = members.tight_copy(pctx->perm); type->kind = TYPE_STRUCT; + node->unique_name = pctx->intern(string_fmt(scratch, "%Q%Q", symbol_prefix, node->name)); } function void @@ -1924,11 +1925,11 @@ resolve_decl(Ast_Decl *ast){ Scratch scratch; node->unique_name = node->name; if(!is_flag_set(node->expr->flags, AST_FOREIGN)){ - node->unique_name = pctx->intern(string_fmt(scratch, "%Q%d", node->name, pctx->lambda_ids++)); + node->unique_name = pctx->intern(string_fmt(scratch, "%Q%Q%d", symbol_prefix, node->name, pctx->lambda_ids++)); } if(is_flag_set(node->flags, AST_OPERATOR_OVERLOAD)){ - node->unique_name = pctx->intern(string_fmt(scratch, "CORE_OPERATOR_%Q%d", node->overload_op_info->name, pctx->lambda_ids++)); + node->unique_name = pctx->intern(string_fmt(scratch, "%QOPERATOR_%Q%d", symbol_prefix, node->overload_op_info->name, pctx->lambda_ids++)); } BREAK();