function Register_Index bc_emit_expr(Bc *b, Ast *ast){ if(!ast) return -1; if(!is_flag_set(ast->flags, AST_EXPR)) compiler_error(ast->pos, "Internal compiler error: Trying to emit expression but it doesn't have appropriate flag"); switch(ast->kind){ // @todo pass type and figure out what to do with untyped ?? CASE(VALUE, Atom){ Register_Index dst = allocate_register(b); emit_load_constant(b, node->pos, dst, node->value); return dst; BREAK(); } CASE(BINARY, Binary){ Register_Index left = bc_emit_expr(b, node->left); Register_Index right = bc_emit_expr(b, node->right); emit_arithmetic(b, node->pos, BC_ADD_S64, left, right, left); release_register(b, right); return left; BREAK(); } default:{} } return -1; } struct Incomplete_Instruction{ Instruction *instruction; Ast_Decl *decl; }; function void emit_stmt(Bc *b, Ast *ast){ switch(ast->kind){ CASE(VAR, Decl){ node->register_index = allocate_register(b); if(is_flag_set(node->flags, AST_VAR_IS_CONST)){ // emit_load_ } BREAK(); } default:{} } } function void compile_to_bc(){ Intern_String intern_main = pctx->intern("main"_s); B32 found_main = false; Bc bc = create_bytecode_interp(); Bc *b = &bc; // Scratch scratch; // auto incomplete = array_make(scratch, 512); Register_Index main_call_register = allocate_register(b); Instruction *load_main_address = emit_load_constant(b, 0, main_call_register, {}); emit_call(b, 0, 0); For_Named(pctx->ordered_decls, ast){ switch(ast->kind){ CASE(LAMBDA, Decl){ Ast_Lambda *lambda = node->lambda; if(!lambda->scope) break; node->bytecode_data_position = b->instruction_pointer; For(node->lambda->args){ it->register_index = allocate_register(b); } For(lambda->scope->stmts){ emit_stmt(b, it); } if(node->name == intern_main){ found_main = true; load_main_address->constant.pointer = (U8 *)node->bytecode_data_position; load_main_address->debug_pos = node->pos; load_main_address->debug_type_flag = TYPE_POINTER; } BREAK(); } CASE(VAR, Decl){ node->bytecode_data_position = exp_alloc(&b->memory, node->type->size, AF_ZeroMemory); if(is_flag_set(node->flags, AST_VAR_IS_CONST)){ switch(node->type->kind){ CASE_UINT: *(U64 *)node->bytecode_data_position = bigint_as_unsigned(&node->big_int_val); break; CASE_SINT: *(S64 *)node->bytecode_data_position = bigint_as_signed(&node->big_int_val); break; CASE_FLOAT: *(F64 *)node->bytecode_data_position = node->f64_val; break; invalid_default_case; } } else if(node->expr) compiler_error(node->pos, "Todo: Global variable with non constant expression"); // if(node->expr){ // Register_Index expression_index = bc_emit_expr(b, node->expr); // Register_Index address_index = allocate_register(b); // emit_load_constant_address(b, node->pos, address_index, node->bytecode_data_position); // emit_memory(b, node->pos, BC_STORE_TO_MEMORY64, address_index, expression_index); // release_register(b, expression_index); // release_register(b, address_index); // } BREAK(); } default: {} } } if(!found_main){ compiler_error(0, "Having a [main] function is required, it's an entry point of the application"); } emit_end(b); run_bytecode_interp(b); destroy_bytecode_interp(b); }