#define gen(...) pctx->gen.addf(__VA_ARGS__) #define genln(...) do{gen("\n"); gen_indent(); gen(__VA_ARGS__); }while(0) 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_BINARY, Ast_Binary){ gen("("); gen_expr(node->left); gen("%s", token_kind_string(node->op).str); gen_expr(node->right); 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); function void gen_block(Ast_Block *block){ gen("{"); global_indent++; For(block->stmts) { genln(""); gen_ast(it[0]); } global_indent--; genln("}"); } function void gen_ast(Ast *ast){ switch(ast->kind){ Ast_Begin(AST_PACKAGE, Ast_Package){ For(node->decls) { genln(""); gen_ast(*it); } Ast_End(); } Ast_Begin(AST_RETURN, Ast_Return){ gen("return"); if(node->expr){ gen(" "); gen_expr(node->expr); } gen(";"); Ast_End(); } Ast_Begin(AST_VAR, Ast_Decl){ Sym *sym = resolved_get(node); gen_simple_decl(sym->type, node->name); if(node->var.expr){ gen(" = "); gen_expr(node->var.expr); } gen(";"); Ast_End(); } Ast_Begin(AST_INIT, Ast_Init){ Sym *sym = resolved_get(node); gen_simple_decl(sym->type, node->ident->intern_val); if(node->expr){ gen(" = "); gen_expr(node->expr); } gen(";"); Ast_End(); } Ast_Begin(AST_IF, Ast_If){ For(node->ifs){ if(it[0]->init) gen_ast(it[0]->init); if(node->ifs.is_first(it)){ genln("if("); gen_expr(it[0]->expr); gen(")"); gen_block(it[0]->block); } else{ genln("else"); if(it[0]->expr){ gen(" if("); gen_expr(it[0]->expr); gen(")"); } gen_block(it[0]->block); } } Ast_End(); } Ast_Begin(AST_CONST, Ast_Decl){ Sym *sym = resolved_get(node); if(sym->type->kind == TYPE_Lambda){ if(node->var.expr->kind == AST_LAMBDA){ Ast_Lambda *lambda = (Ast_Lambda *)node->var.expr; gen("static "); 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(")"); if(lambda->block) { gen_block(lambda->block); } else gen(";"); } else{ gen_simple_decl(sym->type, node->name); gen(" = "); gen_expr(node->var.expr); gen(";"); } } else if(sym->type == type_int){ gen("enum { %s = %lld };", node->name.str, sym->int_val); } else if(sym->type == type_string){ gen("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 String compile_string(String filecontent, String filename = "default_name"_s){ Scratch scratch(thread_ctx.scratch); OS_Heap heap = win32_os_heap_create(false, mib(4), 0); Parse_Ctx ctx = {}; ctx.init(scratch, &heap); pctx = &ctx; lex_restream(&ctx, filecontent, filename); Ast_Package *result = parse_file(); sym_insert_builtins(); gen(R"==(//------------------------------- #define NULL_POINTER 0 #define NULL_LAMBDA 0 //-------------------------------)=="); eval_decl(result); gen_ast(result); exp_destroy(&heap); String string_result = string_flatten(scratch, &pctx->gen); return string_result; } function String compile_file(String filename){ Scratch scratch; String filecontent = os_read_file(scratch, filename); String result = compile_string(filecontent, filename); return result; }