Single header mode sort of working
This commit is contained in:
@@ -471,3 +471,14 @@ string_from_cstring(char *string){
|
|||||||
return result;
|
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++){
|
||||||
|
|
||||||
|
// }
|
||||||
|
// }
|
||||||
@@ -58,12 +58,13 @@ unique_name(Allocator *allocator, Ast *ast){
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
global String prefixed_string_type;
|
||||||
function const char *
|
function const char *
|
||||||
get_ctype_name_for_type(Ast_Type *type){
|
get_ctype_name_for_type(Ast_Type *type){
|
||||||
switch(type->kind){
|
switch(type->kind){
|
||||||
case TYPE_VOID: return "void";
|
case TYPE_VOID: return "void";
|
||||||
case TYPE_BOOL: return "bool";
|
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_CHAR: return "char";
|
||||||
case TYPE_F32: return "float";
|
case TYPE_F32: return "float";
|
||||||
case TYPE_F64: return "double";
|
case TYPE_F64: return "double";
|
||||||
@@ -107,7 +108,7 @@ string_simple_decl_prefix(Allocator *a, Ast_Type *ast){
|
|||||||
}break;
|
}break;
|
||||||
case TYPE_STRUCT: {
|
case TYPE_STRUCT: {
|
||||||
auto constant = (Ast_Decl *)ast->ast;
|
auto constant = (Ast_Decl *)ast->ast;
|
||||||
auto name = constant->name;
|
auto name = constant->unique_name;
|
||||||
String string = string_fmt(a, "%Q ", name);
|
String string = string_fmt(a, "%Q ", name);
|
||||||
String sc = {};
|
String sc = {};
|
||||||
return string_fmt(a, "%Q%Q", sc, string);
|
return string_fmt(a, "%Q%Q", sc, string);
|
||||||
@@ -224,7 +225,7 @@ gen_value(Token *pos, Value a){
|
|||||||
}break;
|
}break;
|
||||||
case TYPE_STRING:{
|
case TYPE_STRING:{
|
||||||
int length = 0;
|
int length = 0;
|
||||||
gen("(CORE_String){(uint8_t *)\"");
|
gen("(%QString){(uint8_t *)\"", symbol_prefix);
|
||||||
for(int i = 0; i < a.intern_val.len; i++){
|
for(int i = 0; i < a.intern_val.len; i++){
|
||||||
if(a.intern_val.str[i] == '\n'){length += 2; gen("\\n");}
|
if(a.intern_val.str[i] == '\n'){length += 2; gen("\\n");}
|
||||||
else if(a.intern_val.str[i] == '\r'){length += 2; gen("\\r");}
|
else if(a.intern_val.str[i] == '\r'){length += 2; gen("\\r");}
|
||||||
@@ -525,8 +526,8 @@ gen_ast(Ast *ast){
|
|||||||
switch(ast->kind){
|
switch(ast->kind){
|
||||||
|
|
||||||
CASE(RUNTIME_ASSERT, Builtin){
|
CASE(RUNTIME_ASSERT, Builtin){
|
||||||
if(node->assert_message.len == 0) gen("CORE_Assert");
|
if(node->assert_message.len == 0) gen("%QAssert", symbol_prefix);
|
||||||
else gen("CORE_AssertMessage");
|
else gen("%QAssertMessage", symbol_prefix);
|
||||||
gen("(");
|
gen("(");
|
||||||
gen_expr(node->expr);
|
gen_expr(node->expr);
|
||||||
if(node->assert_message.len){
|
if(node->assert_message.len){
|
||||||
@@ -545,7 +546,7 @@ gen_ast(Ast *ast){
|
|||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
For(node->expr){
|
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("&");
|
if(!is_array(it->resolved_type)) gen("&");
|
||||||
gen("(");
|
gen("(");
|
||||||
gen_expr(it);
|
gen_expr(it);
|
||||||
@@ -624,7 +625,7 @@ gen_ast(Ast *ast){
|
|||||||
if(node->is_array_traversal){
|
if(node->is_array_traversal){
|
||||||
gen("for(int64_t _i%d = 0; _i%d < ", node->pos->line, node->pos->line);
|
gen("for(int64_t _i%d = 0; _i%d < ", node->pos->line, node->pos->line);
|
||||||
if(is_array(node->cond->resolved_type)){
|
if(is_array(node->cond->resolved_type)){
|
||||||
gen("CORE_BufferSize(");
|
gen("%QBufferSize(", symbol_prefix);
|
||||||
gen_expr(node->cond);
|
gen_expr(node->cond);
|
||||||
gen(")");
|
gen(")");
|
||||||
} else{
|
} else{
|
||||||
@@ -681,7 +682,7 @@ gen_ast(Ast *ast){
|
|||||||
|
|
||||||
CASE(STRUCT, Decl){
|
CASE(STRUCT, Decl){
|
||||||
gen("struct ");
|
gen("struct ");
|
||||||
gen("%Q{", node->name);
|
gen("%Q{", node->unique_name);
|
||||||
global_indent++;
|
global_indent++;
|
||||||
is_inside_struct++;
|
is_inside_struct++;
|
||||||
For(node->scope->decls){
|
For(node->scope->decls){
|
||||||
@@ -695,12 +696,6 @@ gen_ast(Ast *ast){
|
|||||||
BREAK();
|
BREAK();
|
||||||
}
|
}
|
||||||
|
|
||||||
CASE(TYPE, Decl){
|
|
||||||
gen("// Type %Q = ", node->name);
|
|
||||||
gen_simple_decl(node->type_val);
|
|
||||||
BREAK();
|
|
||||||
}
|
|
||||||
|
|
||||||
CASE(ENUM, Decl){
|
CASE(ENUM, Decl){
|
||||||
gen("/*enum %Q{", node->name);
|
gen("/*enum %Q{", node->name);
|
||||||
// @todo add typespec
|
// @todo add typespec
|
||||||
@@ -716,6 +711,7 @@ gen_ast(Ast *ast){
|
|||||||
BREAK();
|
BREAK();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case AST_TYPE:
|
||||||
CASE(CONST, Decl){unused(node);BREAK();}
|
CASE(CONST, Decl){unused(node);BREAK();}
|
||||||
|
|
||||||
CASE(SWITCH, Switch){
|
CASE(SWITCH, Switch){
|
||||||
@@ -761,7 +757,7 @@ gen_ast(Ast *ast){
|
|||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
For(node->vars){
|
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();
|
BREAK();
|
||||||
}
|
}
|
||||||
@@ -782,26 +778,64 @@ function String
|
|||||||
compile_to_c_code(){
|
compile_to_c_code(){
|
||||||
generating_time_begin = os_time();
|
generating_time_begin = os_time();
|
||||||
|
|
||||||
|
prefixed_string_type = string_fmt(pctx->perm, "%QString", symbol_prefix);
|
||||||
|
if(single_header_library_mode){
|
||||||
gen(R"==(
|
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 <stdint.h>
|
||||||
#include <stdbool.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{
|
#ifndef Assert
|
||||||
uint8_t *str;
|
#define Assert(x) do{if(!(x))__debugbreak();}while(0)
|
||||||
int64_t len;
|
#endif
|
||||||
}CORE_String;
|
|
||||||
|
#ifndef AssertMessage
|
||||||
|
#define AssertMessage(x,...) Assert(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MemoryCopy
|
||||||
|
#define MemoryCopy MemoryCopy_
|
||||||
|
|
||||||
static void
|
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 *d = (uint8_t*)dst;
|
||||||
uint8_t *s = (uint8_t*)src;
|
uint8_t *s = (uint8_t*)src;
|
||||||
for(size_t i = 0; i < size; i++){
|
for(size_t i = 0; i < size; i++){
|
||||||
d[i] = s[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){
|
Iter(&pctx->ordered_decls){
|
||||||
auto i = it.item[0];
|
auto i = it.item[0];
|
||||||
if(i->kind == AST_STRUCT){
|
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_member_count = %d, ", t->agg.members.len);
|
||||||
gen(".struct_members = (Type_Info_Struct_Member[]){");
|
gen(".struct_members = (Type_Info_Struct_Member[]){");
|
||||||
For_Named(t->agg.members, m){
|
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("}");
|
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
|
// Generate actual code
|
||||||
Iter(&pctx->ordered_decls){
|
Iter(&pctx->ordered_decls){
|
||||||
if(it.index >= pctx->base_language_ordered_decl_len){
|
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);
|
String string_result = string_flatten(pctx->perm, &pctx->gen);
|
||||||
generating_time_end = os_time();
|
generating_time_end = os_time();
|
||||||
return string_result;
|
return string_result;
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
global B32 emit_line_directives = true;
|
global B32 emit_line_directives = true;
|
||||||
global B32 emit_type_info = true;
|
global B32 emit_type_info = true;
|
||||||
global String symbol_prefix = ""_s;
|
global String symbol_prefix = ""_s;
|
||||||
|
global B32 single_header_library_mode = false;
|
||||||
|
global String single_header_library_name = ""_s;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -293,9 +293,8 @@ int main(int argument_count, char **arguments){
|
|||||||
test_string_builder();
|
test_string_builder();
|
||||||
test_intern_table();
|
test_intern_table();
|
||||||
|
|
||||||
emit_line_directives = false;
|
// emit_line_directives = false;
|
||||||
emit_type_info = false;
|
// emit_type_info = false;
|
||||||
symbol_prefix = "Ray_"_s;
|
|
||||||
if(argument_count > 1){
|
if(argument_count > 1){
|
||||||
String program_name = string_from_cstring(arguments[1]);
|
String program_name = string_from_cstring(arguments[1]);
|
||||||
compile_file(program_name, COMPILE_PRINT_STATS);
|
compile_file(program_name, COMPILE_PRINT_STATS);
|
||||||
|
|||||||
@@ -335,6 +335,7 @@ type_struct_complete(Ast_Type *type, Ast_Decl *node){
|
|||||||
type->padding = type->size - members_size;
|
type->padding = type->size - members_size;
|
||||||
type->agg.members = members.tight_copy(pctx->perm);
|
type->agg.members = members.tight_copy(pctx->perm);
|
||||||
type->kind = TYPE_STRUCT;
|
type->kind = TYPE_STRUCT;
|
||||||
|
node->unique_name = pctx->intern(string_fmt(scratch, "%Q%Q", symbol_prefix, node->name));
|
||||||
}
|
}
|
||||||
|
|
||||||
function void
|
function void
|
||||||
@@ -1924,11 +1925,11 @@ resolve_decl(Ast_Decl *ast){
|
|||||||
Scratch scratch;
|
Scratch scratch;
|
||||||
node->unique_name = node->name;
|
node->unique_name = node->name;
|
||||||
if(!is_flag_set(node->expr->flags, AST_FOREIGN)){
|
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)){
|
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();
|
BREAK();
|
||||||
|
|||||||
Reference in New Issue
Block a user