Phasor 3.3.0
Stack VM based Programming Language
Loading...
Searching...
No Matches
Frontend.cpp
Go to the documentation of this file.
6
7#include <fstream>
8#include <print>
9#include <sstream>
10#include <string>
11#include <version.h>
12#include <sscanf.h>
13
14#include "Frontend.hpp"
15#include <nativeerror.h>
16
17bool startsWith(const std::string &input, const std::string &prefix)
18{
19 if (input.size() >= prefix.size() && input.compare(0, prefix.size(), prefix) == 0)
20 {
21 return true;
22 }
23 return false;
24}
25
26int pulsar::Frontend::runScript(const std::string &source, Phasor::VM *vm)
27{
28 int status = 0;
29 bool ownVM = false;
30 CodeGenerator codegen;
31 Lexer lexer(source);
32 Parser parser(lexer.tokenize());
33
34 auto program = parser.parse();
35 auto bytecode = codegen.generate(*program);
36
37 if (vm == nullptr)
38 {
39 ownVM = true;
40 vm = new VM();
42 }
43
44#if defined(_WIN32)
45 vm->initFFI("plugins");
46#elif defined(__APPLE__)
47 vm->initFFI("/Library/Application Support/org.Phasor.Phasor/plugins");
48#elif defined(__linux__)
49 vm->initFFI("/usr/lib/phasor/plugins/");
50#endif
51
52 vm->setImportHandler([vm](const std::filesystem::path &path) {
53 std::ifstream file(path);
54 if (!file.is_open())
55 {
56 throw std::runtime_error("Could not open imported file: " + path.string());
57 }
58 std::stringstream buffer;
59 buffer << file.rdbuf();
60 runScript(buffer.str(), vm);
61 });
62
63 try
64 {
65 status = vm->run(bytecode);
66
67 if (status != 0)
68 {
69 if (!ownVM)
70 {
71 vm->resetStatus();
72 vm->reset(true, false, false);
73 }
74 }
75 }
76 catch (...)
77 {
78 if (ownVM)
79 delete vm;
80 throw;
81 }
82
83 if (ownVM)
84 delete vm;
85
86 return status;
87}
88
90{
91 int status = 0;
92 bool ownVM = false;
93 CodeGenerator codegen;
94
95 if (vm == nullptr)
96 {
97 ownVM = true;
98 vm = new VM();
100 }
101
102#if defined(_WIN32)
103 vm->initFFI("plugins");
104#elif defined(__APPLE__)
105 vm->initFFI("/Library/Application Support/org.Phasor.Phasor/plugins");
106#elif defined(__linux__)
107 vm->initFFI("/usr/lib/phasor/plugins/");
108#endif
109
110 vm->setImportHandler([](const std::filesystem::path &path) {
111 std::ifstream file(path);
112 if (!file.is_open())
113 {
114 throw std::runtime_error("Could not open imported file: " + path.string());
115 }
116 std::stringstream buffer;
117 buffer << file.rdbuf();
118 runScript(buffer.str());
119 });
120
121 if (status != 0)
122 {
123 if (ownVM)
124 delete vm;
125 std::println(std::cerr, "Failed to create FFI handler!");
126 return status;
127 }
128
129 std::unordered_map<std::string, int> globalVars;
130 int nextVarIdx = 0;
131 std::string line;
132 bool cleanExit = false;
133
134 std::println("Pulsar REPL (using Phasor VM v{})\n"
135 "(C) 2026 Daniel McGuire - Licensed under Apache 2.0\n\n"
136 "Type 'exit()' to quit. Function declarations will not work.",
137 PHASOR_VERSION_STRING);
138
139 while (true)
140 {
141 try
142 {
143 std::print("\n> ");
144 if (!std::getline(std::cin, line))
145 break;
146
147 if (startsWith(line, "exit"))
148 {
149 cleanExit = true;
150 break;
151 }
152 if (line.empty())
153 {
154 std::println(std::cerr, "Empty line");
155 continue;
156 }
157
158 Lexer lexer(line);
159 Parser parser(lexer.tokenize());
160
161 auto program = parser.parse();
162 auto bytecode = codegen.generate(*program, globalVars, nextVarIdx, true);
163
164 globalVars = bytecode.variables;
165 nextVarIdx = bytecode.nextVarIndex;
166
167 status = vm->run(bytecode);
168 }
169 catch (const std::exception &e)
170 {
171 std::string errorMsg = std::string(e.what()) + " | " + vm->getInformation() + "\n";
172 error(errorMsg);
173 }
174 }
175
176 if (ownVM)
177 delete vm;
178
179 if (cleanExit)
180 return 0;
181
182 return status;
183}
bool startsWith(const std::string &input, const std::string &prefix)
Definition Frontend.cpp:17
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
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 void registerFunctions(VM &vm)
Definition StdLib.hpp:35
Virtual Machine.
Definition VM.hpp:33
void setImportHandler(const ImportHandler &handler)
Set the import handler for importing modules.
Definition Utility.cpp:153
void resetStatus()
Definition Utility.cpp:42
int run(const Bytecode &bytecode, const size_t startPC=0)
Run the virtual machine Exits -1 on uncaught exception.
Definition Utility.cpp:88
void initFFI(const std::filesystem::path &path)
Initialize the FFI plugins.
Definition Utility.cpp:51
void reset(const bool &resetStack=true, const bool &resetFunctions=true, const bool &resetVariables=true)
Reset the virtual machine.
Definition Utility.cpp:181
std::string getInformation()
Get VM information for debugging.
Definition Utility.cpp:207
int runRepl(Phasor::VM *vm=nullptr)
Run an REPL.
Definition Frontend.cpp:89
int runScript(const std::string &source, Phasor::VM *vm=nullptr)
Run a script.
Definition Frontend.cpp:26
#define error(msg)
Definition nativeerror.h:8