| 1 | #include "ir_gen.h" |
| 2 | #include "parser.h" |
| 3 | #include "resolver.h" |
| 4 | #include "serializer.h" |
| 5 | #include <cstring> |
| 6 | #include <iostream> |
| 7 | #include <string> |
| 8 | #include <vector> |
| 9 | |
| 10 | namespace nix_irc { |
| 11 | |
| 12 | void print_usage(const char* prog) { |
| 13 | std::cout << "Usage: " << prog << " [options] <input.nix> [output.nixir]\n" |
| 14 | << "\nOptions:\n" |
| 15 | << " -I <path> Add search path for imports\n" |
| 16 | << " --no-imports Disable import resolution\n" |
| 17 | << " --help Show this help\n"; |
| 18 | } |
| 19 | |
| 20 | int run_compile(int argc, char** argv) { |
| 21 | std::string input_file; |
| 22 | std::string output_file; |
| 23 | std::vector<std::string> search_paths; |
| 24 | bool resolve_imports = true; |
| 25 | |
| 26 | int i = 1; |
| 27 | while (i < argc) { |
| 28 | std::string arg = argv[i]; |
| 29 | if (arg == "-I") { |
| 30 | if (i + 1 >= argc) { |
| 31 | std::cerr << "Error: -I requires a path argument\n"; |
| 32 | return 1; |
| 33 | } |
| 34 | search_paths.push_back(argv[++i]); |
| 35 | } else if (arg == "--no-imports") { |
| 36 | resolve_imports = false; |
| 37 | } else if (arg == "--help" || arg == "-h") { |
| 38 | print_usage(argv[0]); |
| 39 | return 0; |
| 40 | } else if (arg[0] != '-') { |
| 41 | input_file = arg; |
| 42 | if (i + 1 < argc && argv[i + 1][0] != '-') { |
| 43 | output_file = argv[++i]; |
| 44 | } |
| 45 | } else { |
| 46 | std::cerr << "Unknown option: " << arg << "\n"; |
| 47 | print_usage(argv[0]); |
| 48 | return 1; |
| 49 | } |
| 50 | i++; |
| 51 | } |
| 52 | |
| 53 | if (input_file.empty()) { |
| 54 | std::cerr << "Error: No input file specified\n"; |
| 55 | print_usage(argv[0]); |
| 56 | return 1; |
| 57 | } |
| 58 | |
| 59 | if (output_file.empty()) { |
| 60 | output_file = input_file + "ir"; |
| 61 | } |
| 62 | |
| 63 | try { |
| 64 | Parser parser; |
| 65 | Resolver resolver; |
| 66 | |
| 67 | for (const auto& path : search_paths) { |
| 68 | resolver.add_search_path(path); |
| 69 | } |
| 70 | |
| 71 | std::cout << "Parsing: " << input_file << "\n"; |
| 72 | auto ast = parser.parse_file(input_file); |
| 73 | |
| 74 | if (!ast) { |
| 75 | std::cerr << "Error: Failed to parse input\n"; |
| 76 | return 1; |
| 77 | } |
| 78 | |
| 79 | std::cout << "Resolving imports...\n"; |
| 80 | |
| 81 | IRGenerator ir_gen; |
| 82 | |
| 83 | std::cout << "Generating IR...\n"; |
| 84 | auto ir = ir_gen.generate(ast); |
| 85 | |
| 86 | IRModule module; |
| 87 | module.version = IR_VERSION; |
| 88 | module.entry = ir; |
| 89 | |
| 90 | std::cout << "Serializing to: " << output_file << "\n"; |
| 91 | Serializer serializer; |
| 92 | serializer.serialize(module, output_file); |
| 93 | |
| 94 | std::cout << "Done!\n"; |
| 95 | return 0; |
| 96 | |
| 97 | } catch (const std::exception& e) { |
| 98 | std::cerr << "Error: " << e.what() << "\n"; |
| 99 | return 1; |
| 100 | } |
| 101 | } |
| 102 | |
| 103 | void print_decompile_usage(const char* prog) { |
| 104 | std::cout << "Usage: " << prog << " decompile <input.nixir>\n"; |
| 105 | } |
| 106 | |
| 107 | int run_decompile(int argc, char** argv) { |
| 108 | if (argc < 3) { |
| 109 | print_decompile_usage(argv[0]); |
| 110 | return 1; |
| 111 | } |
| 112 | |
| 113 | std::string input_file = argv[2]; |
| 114 | |
| 115 | try { |
| 116 | Deserializer deserializer; |
| 117 | auto module = deserializer.deserialize(input_file); |
| 118 | |
| 119 | std::cout << "IR Version: " << module.version << "\n"; |
| 120 | std::cout << "Sources: " << module.sources.size() << "\n"; |
| 121 | std::cout << "Imports: " << module.imports.size() << "\n"; |
| 122 | |
| 123 | return 0; |
| 124 | } catch (const std::exception& e) { |
| 125 | std::cerr << "Error: " << e.what() << "\n"; |
| 126 | return 1; |
| 127 | } |
| 128 | } |
| 129 | |
| 130 | } // namespace nix_irc |
| 131 | |
| 132 | int main(int argc, char** argv) { |
| 133 | if (argc < 2) { |
| 134 | nix_irc::print_usage(argv[0]); |
| 135 | return 1; |
| 136 | } |
| 137 | |
| 138 | std::string cmd = argv[1]; |
| 139 | |
| 140 | if (cmd == "compile" || cmd == "c") { |
| 141 | return nix_irc::run_compile(argc - 1, argv + 1); |
| 142 | } else if (cmd == "decompile" || cmd == "d") { |
| 143 | return nix_irc::run_decompile(argc, argv); |
| 144 | } else if (cmd == "help" || cmd == "--help" || cmd == "-h") { |
| 145 | nix_irc::print_usage(argv[0]); |
| 146 | return 0; |
| 147 | } else { |
| 148 | return nix_irc::run_compile(argc, argv); |
| 149 | } |
| 150 | } |