[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)
|
||||
target_include_directories(nasock PRIVATE ${CMAKE_SOURCE_DIR}/src)
|
||||
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