Phasor 3.1.1
Stack VM based Programming Language
Loading...
Searching...
No Matches
Compiler.cpp
Go to the documentation of this file.
1#include "Compiler.hpp"
7#include <filesystem>
8#include <fstream>
9#include <sstream>
10#include <iostream>
11#include <print>
12
13namespace Phasor
14{
15
16Compiler::Compiler(int argc, char *argv[], char *envp[])
17{
18 m_args.envp = envp;
19 parseArguments(argc, argv);
20}
21
23{
24 if (m_args.showLogo)
25 std::println("Phasor Compiler\n(C) 2026 Daniel McGuire\n");
26 if (m_args.inputFile.empty())
27 {
28 std::println(std::cerr, "Error: No input file provided\n");
29 return 1;
30 }
31
32 if (m_args.irMode)
33 return compileToIR();
34
35 return compileToBytecode();
36}
37
39{
40 if (std::filesystem::path(m_args.inputFile).extension() == ".phsb")
41 {
42 std::println(std::cerr, "Error: Cannot compile a bytecode file (use phasordecomp)");
43 return 1;
44 }
45
46 std::ifstream file(m_args.inputFile);
47 if (!file.is_open())
48 {
49 println(std::cerr, "Could not open file: {}", m_args.inputFile);
50 return 1;
51 }
52
53 std::stringstream buffer;
54 buffer << file.rdbuf();
55 std::string source = buffer.str();
56
57 try
58 {
59 Lexer lexer(source);
60 Parser parser(lexer.tokenize(), m_args.inputFile);
61 auto program = parser.parse();
62 CodeGenerator codegen;
63 auto bytecode = codegen.generate(*program);
64
65 if (m_args.outputFile.empty())
66 {
67 m_args.outputFile = m_args.inputFile;
68 std::filesystem::path path(m_args.outputFile);
69 path.replace_extension(".phsb");
70 m_args.outputFile = path.string();
71 }
72
73 BytecodeSerializer serializer;
74 if (!serializer.saveToFile(bytecode, m_args.outputFile))
75 {
76 std::println(std::cerr, "Failed to save bytecode to: {}", m_args.outputFile);
77 return 1;
78 }
79
80 if (m_args.showLogo)
81 std::println("Compiled successfully: {} -> {}", m_args.inputFile, m_args.outputFile);
82 return 0;
83 }
84 catch (const std::exception &e)
85 {
86 std::println(std::cerr, "Compilation Error: {}", e.what());
87 return 1;
88 }
89}
90
92{
93 if (std::filesystem::path(m_args.inputFile).extension() == ".phir")
94 {
95 std::println(std::cerr, "Error: Cannot compile a Phasor IR file (use phasorasm)");
96 return 1;
97 }
98
99 std::ifstream file(m_args.inputFile);
100 if (!file.is_open())
101 {
102 std::println(std::cerr, "Could not open file: {}\n", m_args.inputFile);
103 return 1;
104 }
105
106 std::stringstream buffer;
107 buffer << file.rdbuf();
108 std::string source = buffer.str();
109
110 try
111 {
112 Lexer lexer(source);
113 Parser parser(lexer.tokenize(), m_args.inputFile);
114 auto program = parser.parse();
115 CodeGenerator codegen;
116 auto bytecode = codegen.generate(*program);
117
118 if (m_args.outputFile.empty())
119 {
120 m_args.outputFile = m_args.inputFile;
121 std::filesystem::path path(m_args.outputFile);
122 path.replace_extension(".phir");
123 m_args.outputFile = path.string();
124 }
125
126 if (!PhasorIR::saveToFile(bytecode, m_args.outputFile))
127 {
128 std::println(std::cerr, "Failed to save Phasor IR to: {}", m_args.outputFile);
129 return 1;
130 }
131
132 std::println("Compiled successfully to IR: {} -> {}", m_args.inputFile, m_args.outputFile);
133 return 0;
134 }
135 catch (const std::exception &e)
136 {
137 std::println(std::cerr, "Compilation Error: {}", e.what());
138 return 1;
139 }
140}
141
142void Compiler::parseArguments(int argc, char *argv[])
143{
144 int defaultArgLocation = 1;
145 for (int i = 1; i < argc; i++)
146 {
147 std::string arg = argv[i];
148
149 if (arg == "-v" || arg == "--verbose")
150 {
151 m_args.verbose = true;
152 }
153 else if (arg == "--no-logo")
154 {
155 m_args.showLogo = false;
156 }
157 else if (arg == "-o" || arg == "--output")
158 {
159 if (i + 1 < argc)
160 {
161 m_args.outputFile = argv[++i];
162 }
163 else
164 {
165 std::print(std::cerr, "Error: {} requires an argument", arg);
166 exit(1);
167 }
168 }
169 else if (arg == "-i" || arg == "--ir")
170 {
171 m_args.irMode = true;
172 }
173 else if (arg == "-h" || arg == "--help")
174 {
175 showHelp(argv[0]);
176 exit(0);
177 }
178 else
179 {
180 defaultArgLocation = i;
181 m_args.inputFile = arg;
182 break; // Stop parsing after finding the input file
183 }
184 }
185 m_args.scriptArgv = argv + defaultArgLocation;
186 m_args.scriptArgc = argc - defaultArgLocation;
187}
188
189void Compiler::showHelp(const std::string &programName)
190{
191 std::string filename = std::filesystem::path(programName).filename().string();
192
193 std::println("Phasor Compiler\n\nUsage:\n"
194 " {} [options] <file.phs>\n\n"
195 "Options:\n -o, --output FILE Specify output file\n"
196 " -i, --ir Compile to IR format (.phir) instead of bytecode\n"
197 " -v, --verbose Enable verbose output\n"
198 " -h, --help Show this help message", filename);
199}
200
201} // namespace Phasor
Bytecode binary format serializer.
bool saveToFile(const Bytecode &bytecode, const std::filesystem::path &filename)
Save bytecode to .phsb file.
Code generator for Phasor VM.
Definition CodeGen.hpp:90
Bytecode generate(const AST::Program &program, const std::map< std::string, int > &existingVars={}, int nextVarIdx=0, bool replMode=false)
Generate bytecode from program.
Definition CodeGen.cpp:7
struct Phasor::Compiler::Args m_args
void parseArguments(int argc, char *argv[])
Definition Compiler.cpp:142
Compiler(int argc, char *argv[], char *envp[])
Definition Compiler.cpp:16
int compileToBytecode()
Definition Compiler.cpp:38
void showHelp(const std::string &programName)
Definition Compiler.cpp:189
Lexer.
Definition Lexer.hpp:13
std::vector< Token > tokenize()
Definition Lexer.cpp:26
Parser.
Definition Parser.hpp:13
std::unique_ptr< AST::Program > parse()
Definition Parser.cpp:73
static bool saveToFile(const Bytecode &bytecode, const std::filesystem::path &filename)
Save bytecode to .phir file.
Definition PhasorIR.cpp:624
The Phasor Programming Language and Runtime.
Definition AST.hpp:11