[web] Added lib for web app
This commit is contained in:
parent
255f10dfae
commit
b7176b39ed
|
@ -100,3 +100,15 @@ target_link_libraries(mat module-used-object)
|
||||||
add_library(nasock SHARED ${CMAKE_SOURCE_DIR}/module/nasocket.cpp)
|
add_library(nasock SHARED ${CMAKE_SOURCE_DIR}/module/nasocket.cpp)
|
||||||
target_include_directories(nasock PRIVATE ${CMAKE_SOURCE_DIR}/src)
|
target_include_directories(nasock PRIVATE ${CMAKE_SOURCE_DIR}/src)
|
||||||
target_link_libraries(nasock module-used-object)
|
target_link_libraries(nasock module-used-object)
|
||||||
|
|
||||||
|
# Add web library
|
||||||
|
add_library(nasal-web SHARED
|
||||||
|
src/nasal_web.cpp
|
||||||
|
${NASAL_OBJECT_SOURCE_FILE}
|
||||||
|
)
|
||||||
|
target_include_directories(nasal-web PRIVATE ${CMAKE_SOURCE_DIR}/src)
|
||||||
|
set_target_properties(nasal-web PROPERTIES
|
||||||
|
C_VISIBILITY_PRESET hidden
|
||||||
|
CXX_VISIBILITY_PRESET hidden
|
||||||
|
VISIBILITY_INLINES_HIDDEN ON
|
||||||
|
)
|
||||||
|
|
|
@ -0,0 +1,112 @@
|
||||||
|
#include "nasal_web.h"
|
||||||
|
#include "nasal_vm.h"
|
||||||
|
#include "nasal_parse.h"
|
||||||
|
#include "nasal_codegen.h"
|
||||||
|
#include "nasal_import.h"
|
||||||
|
#include "nasal_err.h"
|
||||||
|
#include "nasal_lexer.h"
|
||||||
|
#include <string>
|
||||||
|
#include <sstream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
struct NasalContext {
|
||||||
|
nasal::gc gc_instance;
|
||||||
|
std::unique_ptr<nasal::vm> vm_instance;
|
||||||
|
std::string last_result;
|
||||||
|
std::string last_error;
|
||||||
|
|
||||||
|
NasalContext() {
|
||||||
|
vm_instance = std::make_unique<nasal::vm>();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void* nasal_init() {
|
||||||
|
return new NasalContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
void nasal_cleanup(void* context) {
|
||||||
|
delete static_cast<NasalContext*>(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* nasal_eval(void* context, const char* code) {
|
||||||
|
auto* ctx = static_cast<NasalContext*>(context);
|
||||||
|
|
||||||
|
try {
|
||||||
|
nasal::lexer lex;
|
||||||
|
nasal::parse parse;
|
||||||
|
nasal::linker ld;
|
||||||
|
nasal::codegen gen;
|
||||||
|
|
||||||
|
// Create a unique temporary file
|
||||||
|
char temp_filename[] = "/tmp/nasal_eval_XXXXXX.nasal";
|
||||||
|
int fd = mkstemp(temp_filename);
|
||||||
|
if (fd == -1) {
|
||||||
|
throw std::runtime_error("Failed to create temporary file");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write the code to the temporary file
|
||||||
|
std::ofstream temp_file(temp_filename);
|
||||||
|
if (!temp_file.is_open()) {
|
||||||
|
close(fd);
|
||||||
|
throw std::runtime_error("Failed to open temporary file for writing");
|
||||||
|
}
|
||||||
|
temp_file << code;
|
||||||
|
temp_file.close();
|
||||||
|
close(fd); // Close the file descriptor
|
||||||
|
|
||||||
|
// Capture stdout and stderr
|
||||||
|
std::stringstream output;
|
||||||
|
std::stringstream error_output;
|
||||||
|
std::streambuf* old_cout = std::cout.rdbuf(output.rdbuf());
|
||||||
|
std::streambuf* old_cerr = std::cerr.rdbuf(error_output.rdbuf());
|
||||||
|
|
||||||
|
// Process the code by scanning the temporary file
|
||||||
|
if (lex.scan(std::string(temp_filename)).geterr()) {
|
||||||
|
ctx->last_error = error_output.str();
|
||||||
|
std::cout.rdbuf(old_cout);
|
||||||
|
std::cerr.rdbuf(old_cerr);
|
||||||
|
// Remove the temporary file
|
||||||
|
std::remove(temp_filename);
|
||||||
|
return ctx->last_error.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parse.compile(lex).geterr()) {
|
||||||
|
ctx->last_error = error_output.str();
|
||||||
|
std::cout.rdbuf(old_cout);
|
||||||
|
std::cerr.rdbuf(old_cerr);
|
||||||
|
// Remove the temporary file
|
||||||
|
std::remove(temp_filename);
|
||||||
|
return ctx->last_error.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
ld.link(parse, false).chkerr();
|
||||||
|
gen.compile(parse, ld, false, false).chkerr();
|
||||||
|
|
||||||
|
// Run the code
|
||||||
|
ctx->vm_instance->run(gen, ld, {});
|
||||||
|
|
||||||
|
// Restore stdout and stderr and get the outputs
|
||||||
|
std::cout.rdbuf(old_cout);
|
||||||
|
std::cerr.rdbuf(old_cerr);
|
||||||
|
ctx->last_result = output.str() + error_output.str();
|
||||||
|
if (ctx->last_result.empty()) {
|
||||||
|
ctx->last_result = "Execution completed successfully.";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the temporary file
|
||||||
|
std::remove(temp_filename);
|
||||||
|
|
||||||
|
return ctx->last_result.c_str();
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
ctx->last_error = e.what();
|
||||||
|
return ctx->last_error.c_str();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* nasal_get_error(void* context) {
|
||||||
|
auto* ctx = static_cast<NasalContext*>(context);
|
||||||
|
return ctx->last_error.c_str();
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "nasal.h"
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define NASAL_EXPORT __declspec(dllexport)
|
||||||
|
#else
|
||||||
|
#define NASAL_EXPORT __attribute__((visibility("default")))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Main API functions
|
||||||
|
NASAL_EXPORT void* nasal_init();
|
||||||
|
NASAL_EXPORT void nasal_cleanup(void* context);
|
||||||
|
NASAL_EXPORT const char* nasal_eval(void* context, const char* code);
|
||||||
|
NASAL_EXPORT const char* nasal_get_error(void* context);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
Loading…
Reference in New Issue