package compiler import "./backend" import "./checker" import "./lexer" import "./llvm" import "./lower" import "./opt" import "./parser" import "./source" import "core:fmt" import vmem "core:mem/virtual" import "core:os" import "core:os/os2" compile_file :: proc(input_path, output_path: string) -> int { source_bytes, ok := os.read_entire_file(input_path) if !ok { fmt.eprintln("failed to read input:", input_path) return 2 } defer delete(source_bytes) source_file := source.Source{path=input_path, text=string(source_bytes)} diagnostics := source.init_diagnostics(&source_file) defer source.destroy_diagnostics(&diagnostics) lexer_arena: vmem.Arena if err := vmem.arena_init_growing(&lexer_arena); err != nil { fmt.eprintln("failed to initialize lexer arena:", err) return 2 } defer vmem.arena_destroy(&lexer_arena) parser_arena: vmem.Arena if err := vmem.arena_init_growing(&parser_arena); err != nil { fmt.eprintln("failed to initialize parser arena:", err) return 2 } defer vmem.arena_destroy(&parser_arena) checker_arena: vmem.Arena if err := vmem.arena_init_growing(&checker_arena); err != nil { fmt.eprintln("failed to initialize checker arena:", err) return 2 } defer vmem.arena_destroy(&checker_arena) lower_arena: vmem.Arena if err := vmem.arena_init_growing(&lower_arena); err != nil { fmt.eprintln("failed to initialize lowering arena:", err) return 2 } defer vmem.arena_destroy(&lower_arena) tokens := lexer.lex(&source_file, &diagnostics, vmem.arena_allocator(&lexer_arena)) ast_module := parser.parse(&tokens, &diagnostics, vmem.arena_allocator(&parser_arena)) vmem.arena_free_all(&lexer_arena) hir_module := checker.check(&ast_module, &diagnostics, vmem.arena_allocator(&checker_arena)) vmem.arena_free_all(&parser_arena) ir_module := lower.lower(&hir_module, vmem.arena_allocator(&lower_arena)) vmem.arena_free_all(&checker_arena) opt.run(&ir_module) llvm_text := llvm.emit(&ir_module, &diagnostics) defer delete(llvm_text) vmem.arena_free_all(&lower_arena) llvm_path := fmt.tprintf("%s.brolang-%d.ll", output_path, os2.get_pid()) defer _ = os.remove(llvm_path) if err := os.write_entire_file_or_err(llvm_path, transmute([]byte)llvm_text); err != nil { fmt.eprintln("failed to write temporary LLVM IR:", err) return 2 } source.print_all(&diagnostics) if !backend.compile(llvm_path, output_path) { return 2 } if len(diagnostics.items) > 0 { return 1 } return 0 }