22#define setupConsole() \
23 AttachConsole(ATTACH_PARENT_PROCESS); \
24 { FILE* _f; freopen_s(&_f, "CONOUT$", "w", stdout); } \
25 { FILE* _f; freopen_s(&_f, "CONOUT$", "w", stderr); } \
28std::string getCommandLine(LPSTR &lpszCmdLine) {
29 std::string cmdline = lpszCmdLine;
30 return (cmdline.size() >= 2 && cmdline.starts_with(
'"') && cmdline.ends_with(
'"')) ? cmdline.substr(1, cmdline.size() - 2) : cmdline;
37#define PHASOR_API __declspec(dllexport)
38#elif defined(__GNUC__) || defined(__clang__)
39#define PHASOR_API __attribute__((visibility("default")))
48 return PHASOR_VERSION_STRING;
51 PHASOR_API int exec(
void *vmPtr,
const unsigned char *bytecode,
size_t bytecodeSize,
const char *moduleName,
52 int argc,
const char **argv)
56 std::vector<uint8_t> bytecodeData(bytecode, bytecode + bytecodeSize);
59 return NativeRT.
run();
61 catch (
const std::exception &e)
63 msg(std::string(moduleName) +
": " + e.what());
68 PHASOR_API int execFuncInt(
void *vmPtr,
const unsigned char *bytecode,
size_t bytecodeSize,
const char *moduleName,
69 int argc,
const char **argv,
const char *functionName)
73 std::vector<uint8_t> bytecodeData(bytecode, bytecode + bytecodeSize);
78 catch (
const std::exception &e)
80 msg(std::string(moduleName) +
": " + e.what());
86 const char *moduleName,
int argc,
const char **argv,
const char *functionName)
88 static std::string ret;
91 std::vector<uint8_t> bytecodeData(bytecode, bytecode + bytecodeSize);
101 catch (
const std::exception &e)
103 msg(std::string(moduleName) +
": " + e.what());
115 catch (
const std::exception &e)
117 msg(std::string(moduleName) +
": " + e.what());
128 catch (
const std::exception &e)
130 msg(std::string(moduleName) +
": " + e.what());
136 unsigned char *buffer,
size_t bufferSize,
size_t *outSize)
145 if (modulePath && std::filesystem::exists(modulePath))
150 auto ast = parser.
parse();
152 std::vector<uint8_t> data = serializer.
serialize(bc);
155 *outSize = data.size();
160 if (bufferSize < data.size())
163 std::memcpy(buffer, data.data(), data.size());
167 catch (
const std::exception &e)
169 msg(std::string(moduleName) +
": " + e.what());
174 PHASOR_API bool compilePUL(
const char *script,
const char *moduleName,
unsigned char *buffer,
size_t bufferSize,
184 auto ast = parser.
parse();
186 std::vector<uint8_t> data = serializer.
serialize(bc);
189 *outSize = data.size();
194 if (bufferSize < data.size())
197 std::memcpy(buffer, data.data(), data.size());
201 catch (
const std::exception &e)
203 msg(std::string(moduleName) +
": " + e.what());
234 vm->
reset(
true, resetFunctions, resetVariables);
237#if defined(_SHARED) && defined(_WIN32)
238 PHASOR_API void CALLBACK PhasorSourceStringEvaluateA(HWND hwnd, HINSTANCE, LPSTR lpszCmdLine,
int)
241 int exitCode =
evaluatePHS(NULL, getCommandLine(lpszCmdLine).c_str(), __func__,
"",
false);
244 std::string message = std::format(
"\nFailed with code {}\n", exitCode);
245 MessageBoxA(hwnd, message.c_str(), __func__, MB_OK | MB_ICONERROR);
249 PHASOR_API void CALLBACK PhasorSourceFileEvaluateA(HWND hwnd, HINSTANCE, LPSTR lpszCmdLine,
int)
252 std::filesystem::path file = getCommandLine(lpszCmdLine);
253 std::string scriptText;
255 if (!std::filesystem::exists(file))
257 std::string message = std::format(
"File \"{}\" does not exist\n", file.filename().string());
258 MessageBoxA(hwnd, message.c_str(), __func__, MB_OK | MB_ICONERROR);
262 std::ifstream fileStream(file);
265 std::string message = std::format(
"File \"{}\" could not be opened\n", file.filename().string());
266 MessageBoxA(hwnd, message.c_str(), __func__, MB_OK | MB_ICONERROR);
270 fileStream.seekg(0, std::ios::end);
271 scriptText.resize(
static_cast<size_t>(fileStream.tellg()));
272 fileStream.seekg(0, std::ios::beg);
274 fileStream.read(scriptText.data(), scriptText.size());
276 int exitCode =
evaluatePHS(NULL, scriptText.c_str(), __func__, file.parent_path().string().c_str(),
false);
279 std::string message = std::format(
"\nFailed with code {}\n", exitCode);
280 MessageBoxA(hwnd, message.c_str(), __func__, MB_OK | MB_ICONERROR);
284 PHASOR_API void CALLBACK PulsarSourceStringEvaluateA(HWND hwnd, HINSTANCE, LPSTR lpszCmdLine,
int)
287 int exitCode =
evaluatePUL(NULL, getCommandLine(lpszCmdLine).c_str(), __func__);
290 std::string message = std::format(
"\nFailed with code {}\n", exitCode);
291 MessageBoxA(hwnd, message.c_str(), __func__, MB_OK | MB_ICONERROR);
295 PHASOR_API void CALLBACK PulsarSourceFileEvaluateA(HWND hwnd, HINSTANCE, LPSTR lpszCmdLine,
int)
298 std::filesystem::path file = getCommandLine(lpszCmdLine);
299 std::string scriptText;
301 if (!std::filesystem::exists(file))
303 std::string message = std::format(
"File \"{}\" does not exist\n", file.filename().string());
304 MessageBoxA(hwnd, message.c_str(), __func__, MB_OK | MB_ICONERROR);
308 std::ifstream fileStream(file);
311 std::string message = std::format(
"File \"{}\" could not be opened\n", file.filename().string());
312 MessageBoxA(hwnd, message.c_str(), __func__, MB_OK | MB_ICONERROR);
316 fileStream.seekg(0, std::ios::end);
317 scriptText.resize(
static_cast<size_t>(fileStream.tellg()));
318 fileStream.seekg(0, std::ios::beg);
320 fileStream.read(scriptText.data(), scriptText.size());
322 int exitCode =
evaluatePUL(NULL, scriptText.c_str(), __func__);
325 std::string message = std::format(
"\nFailed with code {}\n", exitCode);
326 MessageBoxA(hwnd, message.c_str(), __func__, MB_OK | MB_ICONERROR);
330 PHASOR_API void CALLBACK PhasorBytecodeFileExecuteA(HWND hwnd, HINSTANCE, LPSTR lpszCmdLine,
int)
333 std::filesystem::path file = getCommandLine(lpszCmdLine);
334 if (!std::filesystem::exists(file))
336 std::string message = std::format(
"File \"{}\" does not exist\n", file.filename().string());
337 MessageBoxA(hwnd, message.c_str(), __func__, MB_OK | MB_ICONERROR);
340 if (file.extension().string() !=
".phsb")
342 std::string message = std::format(
"File \"{}\" is not a .phsb file\n", file.filename().string());
343 MessageBoxA(hwnd, message.c_str(), __func__, MB_OK | MB_ICONERROR);
348 std::array<const char *, 2> args = {
"phasorrt.dll", __func__};
350 int exitCode = NativeRT.run();
353 std::string message = std::format(
"\nFailed with code {}\n", exitCode);
354 MessageBoxA(hwnd, message.c_str(), __func__, MB_OK | MB_ICONERROR);
PHASOR_API const char * execFuncString(void *vmPtr, const unsigned char *bytecode, size_t bytecodeSize, const char *moduleName, int argc, const char **argv, const char *functionName)
Executes a function from pre-compiled Phasor bytecode, and casts return to an string.
PHASOR_API bool compilePHS(const char *script, const char *moduleName, const char *modulePath, unsigned char *buffer, size_t bufferSize, size_t *outSize)
Compiles a Phasor Programming Language script into Phasor VM bytecode.
PHASOR_API int evaluatePUL(void *vmPtr, const char *script, const char *moduleName)
Executes a Pulsar Scripting Language script.
PHASOR_API bool compilePUL(const char *script, const char *moduleName, unsigned char *buffer, size_t bufferSize, size_t *outSize)
Compiles a Pulsar Scripting Language script into Phasor VM bytecode.
PHASOR_API int evaluatePHS(void *vmPtr, const char *script, const char *moduleName, const char *modulePath, bool verbose)
Executes a Phasor Programming Language script.
PHASOR_API const char * getVersion()
Get the version string for Phasor VM.
PHASOR_API bool freeState(void *vmPtr)
Frees an existing state instance.
PHASOR_API int execFuncInt(void *vmPtr, const unsigned char *bytecode, size_t bytecodeSize, const char *moduleName, int argc, const char **argv, const char *functionName)
Executes a function from pre-compiled Phasor bytecode, and casts return to an integer.
PHASOR_API int exec(void *vmPtr, const unsigned char *bytecode, size_t bytecodeSize, const char *moduleName, int argc, const char **argv)
Executes pre-compiled Phasor bytecode.
PHASOR_API void * createState()
Creates a new state instance.
PHASOR_API void initStdLib(void *vmPtr)
Register standard library to state instance.
PHASOR_API bool resetState(void *vmPtr, bool resetFunctions, bool resetVariables)
Resets the state.
Bytecode binary format deserializer.
Bytecode loadFromFile(const std::filesystem::path &filename)
Load bytecode from .phsb file.
Bytecode binary format serializer.
std::vector< uint8_t > serialize(const Bytecode &bytecode)
Serialize bytecode to binary buffer.
Code generator for Phasor VM.
Bytecode generate(const AST::Program &program, const std::unordered_map< std::string, int > &existingVars={}, int nextVarIdx=0, bool replMode=false)
Generate bytecode from program.
std::vector< Token > tokenize()
CLI wrapper for running Phasor scripts and bytecode in-process.
int runFunctionInt(std::string functionName)
std::optional< std::string > runFunctionString(std::string functionName)
std::unique_ptr< AST::Program > parse()
void setSourcePath(const std::filesystem::path &path)
static void registerFunctions(VM &vm)
void reset(const bool &resetStack=true, const bool &resetFunctions=true, const bool &resetVariables=true)
Reset the virtual machine.
int runScript(const std::string &source, VM *vm, const std::filesystem::path &path="", bool verbose=false)
Run a script.
int runScript(const std::string &source, Phasor::VM *vm=nullptr)
Run a script.