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