#define genln(...) do{printf("\n"); gen_indent(); gen(__VA_ARGS__); }while(0) #define gen(...) printf(__VA_ARGS__) global S32 global_indent; function void gen_indent(){ for(S32 i = 0; i < global_indent; i++) gen(" "); } // @todo: Gen complicated decl //array 10 ( pointer (pointer array 5 int a)) // int (*(*(a[5])))[10] // // 1 Get to the bottom // 2 Add variable name // 3 Going backwards add arrays and pointers in parens // 4 Add type name on the left side function void gen_simple_decl_prefix(Ast_Resolved_Type *ast){ switch(ast->kind){ case TYPE_Int: gen("int "); break; case TYPE_Bool: gen("bool "); break; case TYPE_Unsigned: gen("unsigned "); break; case TYPE_String: gen("String "); break; case TYPE_Void: gen("void "); break; case TYPE_Pointer:{gen_simple_decl_prefix(ast->base); gen("*");} break; case TYPE_Array: gen_simple_decl_prefix(ast->base); break; case TYPE_Lambda:break; invalid_default_case; } } function void gen_simple_decl_postfix(Ast_Resolved_Type *ast){ switch(ast->kind){ case TYPE_Int: break; case TYPE_Bool: break; case TYPE_Unsigned: break; case TYPE_String: break; case TYPE_Void: break; case TYPE_Pointer: gen_simple_decl_postfix(ast->base); break; case TYPE_Array: gen("[%d]", (int)ast->arr.size); gen_simple_decl_postfix(ast->arr.base); break; case TYPE_Lambda:break; invalid_default_case; } } function void gen_simple_decl(Ast_Resolved_Type *ast, Intern_String name){ if(ast->kind == TYPE_Lambda) { gen_simple_decl_prefix(ast->func.ret); gen("(*%s)(", name.str); For(ast->func.args){ gen_simple_decl_prefix(it[0]); if(it != ast->func.args.end() - 1) gen(", "); } gen(")"); } else{ gen_simple_decl_prefix(ast); if(name.len) { gen("%s", name.str); gen_simple_decl_postfix(ast); } } } function void gen_expr(Ast_Expr *ast){ switch(ast->kind){ Ast_Begin(AST_IDENT, Ast_Expr){ gen("%s", node->intern_val.str); Ast_End(); } Ast_Begin(AST_INT, Ast_Expr){ gen("%lld", node->int_val); Ast_End(); } Ast_Begin(AST_STR, Ast_Expr){ gen("LIT(\"%s\")", node->intern_val.str); Ast_End(); } Ast_Begin(AST_INDEX, Ast_Expr){ gen_expr(node->index.expr); gen("["); gen_expr(node->index.index); gen("]"); Ast_End(); } Ast_Begin(AST_UNARY, Ast_Expr){ switch(node->unary.op){ case TK_Pointer: { gen("(*"); gen_expr(node->unary.expr); gen(")"); } break; case TK_Dereference: { gen("(&"); gen_expr(node->unary.expr); gen(")"); } break; invalid_default_case; } Ast_End(); } Ast_Begin(AST_CAST, Ast_Expr){ gen("("); gen("("); gen_simple_decl(node->cast.typespec->resolved_type, {}); gen(")"); gen_expr(node->cast.expr); gen(")"); Ast_End(); } Ast_Begin(AST_COMPOUND, Ast_Expr){ gen("("); gen_simple_decl(node->compound.type, {}); gen(")"); gen("{"); For(node->compound.exprs){ auto comp = it[0]->compound_item; if(comp.name){ gen("["); gen_expr(comp.name); gen("] = "); } if(comp.index){ gen("["); gen_expr(comp.index); gen("] = "); } assert(comp.item); gen_expr(comp.item); if(!node->compound.exprs.is_last(it)) gen(", "); } gen("}"); Ast_End(); } invalid_default_case; } } function void gen_ast(Ast *ast){ switch(ast->kind){ Ast_Begin(AST_PACKAGE, Ast_Package){ For(node->decls) gen_ast(*it); Ast_End(); } Ast_Begin(AST_VAR, Ast_Decl){ genln(""); Sym *sym = sym_get(node->name); gen_simple_decl(sym->type, node->name); if(node->var.expr){ gen(" = "); gen_expr(node->var.expr); } gen(";"); Ast_End(); } Ast_Begin(AST_CONST, Ast_Decl){ Sym *sym = sym_get(node->name); if(sym->type->kind == TYPE_Lambda){ if(node->var.expr->kind == AST_LAMBDA){ Ast_Lambda *lambda = (Ast_Lambda *)node->var.expr; genln(""); gen_simple_decl(lambda->ret->resolved_type, node->name); gen("("); For(lambda->params){ assert(it[0]->kind == AST_LAMBDA_PARAM); gen_simple_decl(it[0]->lambda_param.typespec->resolved_type, it[0]->lambda_param.name); if(it != (lambda->params.end() - 1)) gen(", "); } gen(")"); } else{ genln(""); gen_simple_decl(sym->type, node->name); gen(" = "); gen_expr(node->var.expr); gen(";"); } } else if(sym->type == type_int){ genln("enum { %s = %lld };", node->name.str, sym->int_val); } else if(sym->type == type_string){ genln("String %s = LIT(\"%s\");", node->name.str, sym->intern_val.str); } else{ parsing_error(node->pos, "Unhandled type of constant expression"); } Ast_End(); } invalid_default_case; } } function void test_gen(){ TEST_PARSER(); String filename = "test3.kl"_s; String file_content = os_read_file(scratch, filename); lex_restream(&ctx, file_content, filename); Ast_Package *result = parse_file(); sym_insert_builtins(); eval_decl(result); gen(R"==( #define null_pointer 0 #define null_lambda 0 )=="); gen_ast(result); __debugbreak(); }