C codegen
This commit is contained in:
126
codegen_c.c
Normal file
126
codegen_c.c
Normal 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user