Single header mode sort of working

This commit is contained in:
Krzosa Karol
2022-10-02 13:40:04 +02:00
parent e098663d82
commit b10f3840df
5 changed files with 88 additions and 30 deletions

View File

@@ -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<String_Replace> pairs){
// for(int i = 0; i < string.len; i++){
// }
// }

View File

@@ -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 <stdint.h>
#include <stdbool.h>
#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;

View File

@@ -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;

View File

@@ -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);

View File

@@ -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();