#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_Atom){ gen("%s", node->intern_val.str); Ast_End(); } Ast_Begin(AST_INT, Ast_Atom){ gen("%lld", node->int_val); Ast_End(); } Ast_Begin(AST_STR, Ast_Atom){ gen("LIT(\"%s\")", node->intern_val.str); Ast_End(); } Ast_Begin(AST_INDEX, Ast_Index){ gen_expr(node->expr); gen("["); gen_expr(node->index); gen("]"); Ast_End(); } Ast_Begin(AST_UNARY, Ast_Unary){ switch(node->op){ case TK_Pointer: { gen("(*"); gen_expr(node->expr); gen(")"); } break; case TK_Dereference: { gen("(&"); gen_expr(node->expr); gen(")"); } break; invalid_default_case; } Ast_End(); } Ast_Begin(AST_CAST, Ast_Cast){ gen("("); gen("("); gen_simple_decl(node->typespec->resolved_type, {}); gen(")"); gen_expr(node->expr); gen(")"); Ast_End(); } Ast_Begin(AST_COMPOUND, Ast_Compound){ gen("("); gen_simple_decl(node->type, {}); gen(")"); gen("{"); For(node->exprs){ auto comp = it[0]; 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->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->args){ assert(it[0]->kind == AST_LAMBDA_ARG); gen_simple_decl(it[0]->typespec->resolved_type, it[0]->name); if(it != (lambda->args.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(); }