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