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