C codegen

This commit is contained in:
Krzosa Karol
2022-05-03 20:08:13 +02:00
parent 8c04044ea2
commit 557dde1936
11 changed files with 573 additions and 281 deletions

126
codegen_c.c Normal file
View File

@@ -0,0 +1,126 @@
function void gen_decl(Parser *p, Decl *node);
function void
gen_typespec(Parser *p, Typespec *spec, B32 is_left){
switch(spec->kind) {
case TS_Name: {
if(is_left) lex_print("%s", spec->name.s.str);
} break;
case TS_Pointer: {
gen_typespec(p, spec->base,is_left);
if(is_left) lex_print("*");
} break;
case TS_Array: {
gen_typespec(p, spec->array_spec.base,is_left);
if(!is_left){
lex_print("[");
expr_print(p, spec->array_spec.size);
lex_print("]");
}
} break;
case TS_Function: {
invalid_codepath;
} break;
default: {invalid_codepath;} break;
}
}
function Typespec *
typespec_get_func(Typespec *type){
switch(type->kind){
case TS_Name:{return 0;} break;
case TS_Pointer:{return typespec_get_func(type->base);} break;
case TS_Array:{return typespec_get_func(type->array_spec.base);} break;
case TS_Function:{return type;} break;
default: {invalid_codepath;} break;
}
return 0;
}
function void
gen_decl(Parser *p, Decl *node){
switch(node->kind) {
case DECL_List: {
for(Decl *n = node->list.first; n; n=n->next){
gen_decl(p,n);
lex_new_line();
}
} break;
case DECL_Variable:{
Typespec *func = typespec_get_func(node->variable_decl.type);
if(!func){
gen_typespec(p, node->variable_decl.type, true);
lex_print(" %s", node->name.s.str);
gen_typespec(p, node->variable_decl.type, false);
}
else{
gen_typespec(p, func->function_spec.ret, true);
lex_print("(*");
lex_print("%s", node->name.s.str);
lex_print(")");
lex_print("(");
for(Typespec *t = func->function_spec.first; t; t=t->next){
gen_typespec(p, t, true);
gen_typespec(p, t, false);
if(t != func->function_spec.last) lex_print(", ");
}
lex_print(")");
}
print_assign_expr(p,node->variable_decl.expr);
lex_print(";");
} break;
case DECL_Typedef:{
lex_print("typedef %s ", node->name.s.str);
gen_typespec(p, node->typedef_decl.type, true);
gen_typespec(p, node->typedef_decl.type, false);
lex_print(";");
} break;
case DECL_Struct:
case DECL_Union :{
U8 *struct_name = node->kind==DECL_Struct ? (U8*)"struct" : (U8*)"union";
U8 *name = node->name.s.str;
if(node->struct_decl.kind == STRUCT_Base)
lex_print("typedef %s %s %s;\n", struct_name, name, name);
lex_print("%s %s{\n", struct_name, name?name:(U8*)"");
for(Decl *n = node->struct_decl.first; n; n=n->next){
gen_decl(p, n);
lex_print("\n");
}
lex_print("};");
if(node->struct_decl.kind == STRUCT_Base)
lex_print("\n");
} break;
case DECL_Enum:{
lex_print("enum %s", node->name.s.str);
if(!intern_compare(node->enum_decl.typespec->name, intern_s64)){
lex_print(" : ");
lex_print("%s", node->enum_decl.typespec->name.s.str);
}
lex_print("{\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){
lex_print("%.*s%s", (int)prefix.len, prefix.str, n->name.s.str);
print_assign_expr(p, n->expr);
lex_print(",\n");
}
lex_print("};\n");
} break;
default: {invalid_codepath;} break;
}
}