476 lines
12 KiB
C
476 lines
12 KiB
C
function void gen_decl(Decl *node);
|
|
function void gen_cdecl(Typespec *type, String str);
|
|
function void gen_stmt_list(Stmt *stmt);
|
|
|
|
global String_List *glist;
|
|
global Arena *gscratch;
|
|
global Parser *genp;
|
|
#define strf(...) string_listf(gscratch, glist, __VA_ARGS__)
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// String replacing util
|
|
//-----------------------------------------------------------------------------
|
|
typedef struct String_Map String_Map;
|
|
struct String_Map{
|
|
String replace;
|
|
String with;
|
|
};
|
|
|
|
function void
|
|
string_mapped_print(String string, String_Map *map, SizeU count){
|
|
Tokens tokens = lex_stream(string, lit("string_mapped_print"));
|
|
for(Token *t = tokens.tokens; t != tokens.tokens + tokens.len; t++){
|
|
String string = t->string;
|
|
for(SizeU i = 0; i < count; i++){
|
|
if(string_compare(string, map[i].replace)){
|
|
string = map[i].with;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(t->kind == TK_At) continue;
|
|
if(string_compare(t->string,keyword_function.s)) strf("\n");
|
|
strf("%.*s", (int)string.len, string.str);
|
|
if(string_compare(t->string,keyword_function.s)) strf("\n");
|
|
if(t->kind == TK_OpenBrace) strf("\n");
|
|
if(t->kind == TK_CloseBrace && t[1].kind != TK_Semicolon) strf("\n");
|
|
if(t->kind == TK_Semicolon) strf("\n");
|
|
if(t->kind == TK_Identifier && (t[1].kind == TK_Keyword || t[1].kind == TK_Identifier)) strf(" ");
|
|
if(t->kind == TK_Keyword) strf(" ");
|
|
if(t->kind == TK_Comma) strf(" ");
|
|
}
|
|
free(tokens.tokens);
|
|
}
|
|
#define STR(X) lit(#X)
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Codegen
|
|
//-----------------------------------------------------------------------------
|
|
|
|
function void
|
|
token_strf(Token *token){
|
|
strf("%.*s", (S32)token->len, token->str);
|
|
}
|
|
|
|
function void
|
|
gen_expr(Expr *expr){
|
|
switch(expr->kind) {
|
|
case EK_Atom: {
|
|
token_strf(expr->token);
|
|
} break;
|
|
|
|
case EK_Sizeof:{
|
|
strf("sizeof(");
|
|
if(expr->size_of.kind == SIZEOF_Expr){
|
|
gen_expr(expr->size_of.expr);
|
|
}
|
|
else{
|
|
assert(expr->size_of.kind == SIZEOF_Type);
|
|
gen_cdecl(expr->size_of.type, string_empty);
|
|
}
|
|
strf(")");
|
|
}break;
|
|
|
|
case EK_Binary:{
|
|
strf("(");
|
|
gen_expr(expr->binary.left);
|
|
token_strf(expr->token);
|
|
gen_expr(expr->binary.right);
|
|
strf(")");
|
|
} break;
|
|
case EK_Unary:{
|
|
strf("(");
|
|
token_strf(expr->token);
|
|
gen_expr(expr->unary.expr);
|
|
strf(")");
|
|
} break;
|
|
|
|
case EK_Ternary:{
|
|
strf("(");
|
|
gen_expr(expr->ternary.cond);
|
|
strf("?");
|
|
gen_expr(expr->ternary.on_true);
|
|
strf(":");
|
|
gen_expr(expr->ternary.on_false);
|
|
strf(")");
|
|
} break;
|
|
case EK_List:{
|
|
strf("(");
|
|
for(Expr *n = expr->list.first; n; n=n->next){
|
|
gen_expr(n);
|
|
if(n!=expr->list.last) strf(",");
|
|
}
|
|
strf(")");
|
|
}break;
|
|
|
|
case EK_Cast:{
|
|
strf("(");
|
|
strf("(");
|
|
gen_cdecl(expr->cast.type, string_empty);
|
|
strf(")");
|
|
gen_expr(expr->cast.expr);
|
|
strf(")");
|
|
} break;
|
|
|
|
case EK_Index:{
|
|
gen_expr(expr->index.atom);
|
|
strf("[");
|
|
gen_expr(expr->index.index);
|
|
strf("]");
|
|
}break;
|
|
|
|
case EK_Call:{
|
|
gen_expr(expr->call.atom);
|
|
strf("(");
|
|
gen_expr(expr->call.list);
|
|
strf(")");
|
|
}break;
|
|
default: {invalid_codepath;} break;
|
|
}
|
|
}
|
|
|
|
function String
|
|
gen_cdecl_paren(String str, String original){
|
|
if(string_is_empty(original) || original.str[0] == '['){
|
|
return str;
|
|
}
|
|
else{
|
|
String result = string_fmt(gscratch, "(%.*s)", (int)str.len, str.str);
|
|
return result;
|
|
}
|
|
}
|
|
|
|
function String
|
|
gen__cdecl(Typespec *type, String str){
|
|
switch(type->kind) {
|
|
case TS_Name: {
|
|
String space = string_is_empty(str) ? lit(""):lit(" ");
|
|
String result = string_fmt(gscratch, "%s%s%.*s", type->name.s.str, space.str, (int)str.len, str.str);
|
|
return result;
|
|
} break;
|
|
case TS_Pointer: {
|
|
String pointer = string_fmt(gscratch, "*%.*s", (int)str.len, str.str);
|
|
String add_paren = gen_cdecl_paren(pointer, str);
|
|
String result = gen__cdecl(type->base, add_paren);
|
|
return result;
|
|
} break;
|
|
case TS_Array: {
|
|
String left = string_fmt(gscratch, "%s[", str.str);
|
|
|
|
String_List *save = glist;
|
|
String_List list = {0};
|
|
glist = &list;
|
|
gen_expr(type->array_spec.size);
|
|
String expr_string = string_list_flatten(gscratch, glist);
|
|
glist = save;
|
|
|
|
|
|
String right = string_fmt(gscratch, "%s%s]", left.str, expr_string.str);
|
|
String paren = gen_cdecl_paren(right, str);
|
|
String result = gen__cdecl(type->array_spec.base, paren);
|
|
return result;
|
|
} break;
|
|
case TS_Function: {
|
|
String result = string_fmt(gscratch, "(*%s)(", str.str);
|
|
if (type->function_spec.first == 0) {
|
|
result= string_fmt(gscratch, "%svoid", result.str);
|
|
}
|
|
else {
|
|
for(Typespec *n = type->function_spec.first; n; n=n->next){
|
|
String arg = gen__cdecl(n, string_empty);
|
|
result = string_fmt(gscratch, "%s%s", result.str, arg.str);
|
|
if(n != type->function_spec.last)
|
|
result = string_fmt(gscratch, "%s, ", result.str);
|
|
}
|
|
}
|
|
result = string_fmt(gscratch, "%s)", result.str);
|
|
result = gen__cdecl(type->function_spec.ret, result);
|
|
return result;
|
|
} break;
|
|
default: {invalid_codepath;} break;
|
|
}
|
|
return string_empty;
|
|
}
|
|
|
|
function void
|
|
gen_cdecl(Typespec *type, String str){
|
|
String string = gen__cdecl(type, str);
|
|
strf("%.*s", (int)string.len, string.str);
|
|
}
|
|
|
|
function void
|
|
gen_assign_expr(Expr *expr){
|
|
if(expr){
|
|
strf(" = ");
|
|
gen_expr(expr);
|
|
}
|
|
}
|
|
|
|
function void
|
|
gen_function_decl(Decl *node){
|
|
strf("function ");
|
|
gen_cdecl(node->function_decl.ret, string_empty);
|
|
strf(" %s(", node->name.s.str);
|
|
for(Decl_Function_Arg *arg = node->function_decl.first; arg; arg=arg->next){
|
|
gen_cdecl(arg->typespec, arg->name.s);
|
|
if(arg!=node->function_decl.last) strf(", ");
|
|
}
|
|
strf(")");
|
|
}
|
|
|
|
typedef struct Macro{
|
|
Intern_String name;
|
|
Note *param_type;
|
|
Note *param_expr;
|
|
Decl *decl;
|
|
}Macro;
|
|
global Macro macros[32];
|
|
global S32 macros_i;
|
|
|
|
function void
|
|
gen_forward_decl(Decl *node){
|
|
U8 *name = node->name.s.str;
|
|
switch(node->kind) {
|
|
case DECL_List: {
|
|
for(Decl *n = node->list.first; n; n=n->next){
|
|
gen_forward_decl(n);
|
|
}
|
|
} break;
|
|
|
|
case DECL_Variable:{
|
|
} break;
|
|
|
|
case DECL_Typedef:{
|
|
} break;
|
|
|
|
case DECL_Function:{
|
|
gen_function_decl(node);
|
|
strf(";\n");
|
|
}break;
|
|
|
|
case DECL_Struct:
|
|
case DECL_Union :{
|
|
Note *note = decl_find_note(node, lit("register"));
|
|
if(note){
|
|
Note *param_expr = decl_find_note(node, lit("param_expr"));
|
|
Note *param_type = decl_find_note(node, lit("param_type"));
|
|
macros[macros_i++] = (Macro){
|
|
.name=node->name,
|
|
.param_type=param_type,
|
|
.param_expr=param_expr,
|
|
.decl=node
|
|
};
|
|
}
|
|
else{
|
|
U8 *struct_name = node->kind==DECL_Struct ? (U8*)"struct" : (U8*)"union";
|
|
if(node->struct_decl.kind == STRUCT_Base)
|
|
strf("typedef %s %s %s;\n", struct_name, name, name);
|
|
}
|
|
} break;
|
|
|
|
case DECL_Enum:{
|
|
} break;
|
|
|
|
default: {invalid_codepath;} break;
|
|
}
|
|
}
|
|
|
|
function void
|
|
gen_decl(Decl *node){
|
|
U8 *name = node->name.s.str;
|
|
|
|
switch(node->kind) {
|
|
case DECL_List: {
|
|
for(Decl *n = node->list.first; n; n=n->next){
|
|
gen_decl(n);
|
|
strf("\n");
|
|
}
|
|
} break;
|
|
|
|
case DECL_Variable:{
|
|
gen_cdecl(node->variable_decl.type, node->name.s);
|
|
gen_assign_expr(node->variable_decl.expr);
|
|
strf(";");
|
|
} break;
|
|
|
|
case DECL_Typedef:{
|
|
strf("typedef ");
|
|
gen_cdecl(node->typedef_decl.type, node->name.s);
|
|
strf(";");
|
|
} break;
|
|
|
|
case DECL_Struct:
|
|
case DECL_Union :{
|
|
Note *note = decl_find_note(node, lit("register"));
|
|
if(note){
|
|
Arena_Checkpoint checkpoint = arena_checkpoint(gscratch);
|
|
Pointer_Array array = gather(checkpoint.arena, node, GATHER_Decl|GATHER_Typespec, TRAVERS_All);
|
|
Intern_String based = intern_string(genp, lit("Based_Type_Represent"));
|
|
Intern_String type = intern_string(genp, lit("Type"));
|
|
for(Pointer it = pointer_array_iter_begin(&array); it.typespec; it = pointer_array_iter_next(&array)){
|
|
if(it.kind == PK_Typespec){
|
|
Typespec *typespec = it.typespec;
|
|
assert(typespec->kind == TS_Name || typespec->kind == TS_Pointer || typespec->kind == TS_Array || typespec->kind == TS_Function);
|
|
if(typespec->kind == TS_Name){
|
|
if(intern_compare(typespec->name, type)){
|
|
typespec->name = based;
|
|
}
|
|
}
|
|
}
|
|
else if(it.kind == PK_Decl){
|
|
Decl *decl = it.decl;
|
|
if(decl->kind == DECL_Struct || decl->kind == DECL_Function){
|
|
if(intern_compare(decl->name, type)){
|
|
decl->name = based;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
arena_restore(checkpoint);
|
|
}
|
|
U8 *struct_name = node->kind==DECL_Struct ? (U8*)"struct" : (U8*)"union";
|
|
strf("%s", struct_name);
|
|
if(node->struct_decl.kind == STRUCT_Base)
|
|
strf(" %s", node->name.s.str);
|
|
strf("{\n");
|
|
for(Decl *n = node->struct_decl.first; n; n=n->next){
|
|
gen_decl(n);
|
|
strf("\n");
|
|
}
|
|
strf("}");
|
|
if(node->struct_decl.kind == STRUCT_Nested)
|
|
strf("%.*s", (int)node->name.s.len, node->name.s.str);
|
|
|
|
strf(";");
|
|
if(node->struct_decl.kind == STRUCT_Base)
|
|
strf("\n");
|
|
|
|
} break;
|
|
|
|
case DECL_Enum:{
|
|
strf("typedef enum %s", name);
|
|
if(!intern_compare(node->enum_decl.typespec->name, intern_s64)){
|
|
strf(" : ");
|
|
strf("%s", node->enum_decl.typespec->name.s.str);
|
|
}
|
|
strf("{\n");
|
|
|
|
String prefix = decl_find_string_note(node, lit("prefix"), string_empty);
|
|
for(Decl_Enum_Child *n = node->enum_decl.first; n; n=n->next){
|
|
strf("%.*s%s", (int)prefix.len, prefix.str, n->name.s.str);
|
|
gen_assign_expr(n->expr);
|
|
strf(",\n");
|
|
}
|
|
|
|
strf("}%s;\n", name);
|
|
} break;
|
|
|
|
case DECL_Function:{
|
|
gen_function_decl(node);
|
|
gen_stmt_list(node->function_decl.body);
|
|
} break;
|
|
|
|
default: {invalid_codepath;} break;
|
|
}
|
|
}
|
|
|
|
function void
|
|
gen_stmt_list(Stmt *stmt){
|
|
strf("{\n");
|
|
for(Stmt *s = stmt->list.first; s; s=s->next){
|
|
gen_stmt(s);
|
|
strf("\n");
|
|
}
|
|
strf("}");
|
|
}
|
|
|
|
function void
|
|
gen_stmt(Stmt *stmt){
|
|
switch(stmt->kind) {
|
|
case STMT_List: {
|
|
gen_stmt_list(stmt);
|
|
} break;
|
|
case STMT_Return:{
|
|
strf("return ");
|
|
gen_expr(stmt->ret.expr);
|
|
strf(";");
|
|
} break;
|
|
case STMT_If:{
|
|
strf("if ");
|
|
gen_expr(stmt->stmt_if.cond);
|
|
gen_stmt_list(stmt->stmt_if.body);
|
|
for(Stmt_If *s = stmt->stmt_if.next; s; s=s->next){
|
|
if(s->next){
|
|
strf("else if ");
|
|
gen_expr(s->cond);
|
|
gen_stmt_list(s->body);
|
|
}
|
|
else{
|
|
strf("else");
|
|
gen_stmt_list(s->body);
|
|
}
|
|
}
|
|
} break;
|
|
case STMT_Expr: {
|
|
gen_expr(stmt->expr);
|
|
strf(";");
|
|
} break;
|
|
case STMT_Decl: {
|
|
gen_decl(stmt->decl);
|
|
} break;
|
|
default: {invalid_codepath;} break;
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
global Decl *gen_parent;
|
|
function void
|
|
gen_code(Decl *node){
|
|
U8 *name = node->name.s.str;
|
|
|
|
switch(node->kind) {
|
|
case DECL_List: {
|
|
for(Decl *n = node->list.first; n; n=n->next){
|
|
gen_code(n);
|
|
}
|
|
} break;
|
|
|
|
case DECL_Variable:{
|
|
} break;
|
|
|
|
case DECL_Typedef:{
|
|
} break;
|
|
|
|
case DECL_Struct:
|
|
case DECL_Union :{
|
|
gen_parent = node;
|
|
for(Decl *n = node->struct_decl.first; n; n=n->next){
|
|
gen_code(n);
|
|
}
|
|
|
|
} break;
|
|
|
|
case DECL_Enum:{
|
|
} break;
|
|
|
|
default: {invalid_codepath;} break;
|
|
}
|
|
}
|
|
|
|
String_List list;
|
|
function void
|
|
gen_begin(Arena *scratch, Parser *p){
|
|
list = (String_List){0};
|
|
gscratch = scratch;
|
|
glist = &list;
|
|
genp = p;
|
|
}
|
|
|
|
function void
|
|
gen_end(){
|
|
String result = string_list_flatten(gscratch, glist);
|
|
lex_print("%s", result.str);
|
|
}
|