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