aboutsummaryrefslogtreecommitdiff
path: root/src/yue_wasm.cpp
diff options
context:
space:
mode:
authorLi Jin <dragon-fly@qq.com>2021-04-16 17:25:39 +0800
committerLi Jin <dragon-fly@qq.com>2021-04-16 17:25:39 +0800
commitce9f6632635222b38ef0b37b4b1273da4a1877b4 (patch)
tree04d4d3ea81749989015434333d3db1add7b0195a /src/yue_wasm.cpp
parent3355b7c475bc4a3bc8c4f2e8a2f504bb3ccb9395 (diff)
downloadyuescript-ce9f6632635222b38ef0b37b4b1273da4a1877b4.tar.gz
yuescript-ce9f6632635222b38ef0b37b4b1273da4a1877b4.tar.bz2
yuescript-ce9f6632635222b38ef0b37b4b1273da4a1877b4.zip
fix small issues, add web assembly support.
Diffstat (limited to 'src/yue_wasm.cpp')
-rw-r--r--src/yue_wasm.cpp160
1 files changed, 160 insertions, 0 deletions
diff --git a/src/yue_wasm.cpp b/src/yue_wasm.cpp
new file mode 100644
index 0000000..fd8b150
--- /dev/null
+++ b/src/yue_wasm.cpp
@@ -0,0 +1,160 @@
1#include "yuescript/yue_compiler.h"
2
3extern "C" {
4#include "lua.h"
5#include "lauxlib.h"
6#include "lualib.h"
7int luaopen_yue(lua_State* L);
8} // extern "C"
9
10static void openlibs(void* state) {
11 lua_State* L = static_cast<lua_State*>(state);
12 luaL_openlibs(L);
13 luaopen_yue(L);
14}
15
16#define YUE_ARGS nullptr,openlibs
17
18#include <string_view>
19using namespace std::string_view_literals;
20#include <emscripten/bind.h>
21using namespace emscripten;
22
23struct YueResult
24{
25 std::string codes;
26 std::string err;
27};
28
29YueResult tolua(const std::string& codes, bool reserveLineNumber = true, bool implicitReturnRoot = true, bool useSpaceOverTab = true) {
30 yue::YueConfig config;
31 config.reserveLineNumber = reserveLineNumber;
32 config.implicitReturnRoot = implicitReturnRoot;
33 config.useSpaceOverTab = useSpaceOverTab;
34 auto result = yue::YueCompiler{YUE_ARGS}.compile(codes, config);
35 return {result.codes, result.error};
36}
37
38std::string version() { return std::string(yue::version); }
39
40#define _DEFER(code,line) std::shared_ptr<void> _defer_##line(nullptr, [&](auto){code;})
41#define DEFER(code) _DEFER(code,__LINE__)
42
43void pushYue(lua_State* L, std::string_view name) {
44 lua_getglobal(L, "package"); // package
45 lua_getfield(L, -1, "loaded"); // package loaded
46 lua_getfield(L, -1, "yue"); // package loaded yue
47 lua_pushlstring(L, &name.front(), name.size()); // package loaded yue name
48 lua_gettable(L, -2); // loaded[name], package loaded yue item
49 lua_insert(L, -4); // item package loaded yue
50 lua_pop(L, 3); // item
51}
52
53void pushOptions(lua_State* L, int lineOffset) {
54 lua_newtable(L);
55 lua_pushliteral(L, "lint_global");
56 lua_pushboolean(L, 0);
57 lua_rawset(L, -3);
58 lua_pushliteral(L, "implicit_return_root");
59 lua_pushboolean(L, 1);
60 lua_rawset(L, -3);
61 lua_pushliteral(L, "reserve_line_number");
62 lua_pushboolean(L, 1);
63 lua_rawset(L, -3);
64 lua_pushliteral(L, "space_over_tab");
65 lua_pushboolean(L, 0);
66 lua_rawset(L, -3);
67 lua_pushliteral(L, "same_module");
68 lua_pushboolean(L, 1);
69 lua_rawset(L, -3);
70 lua_pushliteral(L, "line_offset");
71 lua_pushinteger(L, lineOffset);
72 lua_rawset(L, -3);
73}
74
75std::string exec(const std::string& codes) {
76 lua_State* L = luaL_newstate();
77 openlibs(L);
78 DEFER(lua_close(L));
79 auto execStr = [&](const std::string& s) {
80 std::string result;
81 pushYue(L, "insert_loader"sv);
82 if (lua_pcall(L, 0, 0, 0) != 0) {
83 result += lua_tostring(L, -1);
84 result += '\n';
85 return result;
86 }
87 pushYue(L, "loadstring"sv);
88 lua_pushlstring(L, s.c_str(), s.size());
89 lua_pushliteral(L, "=(eval str)");
90 if (lua_pcall(L, 2, 2, 0) != 0) {
91 result += lua_tostring(L, -1);
92 result += '\n';
93 return result;
94 }
95 if (lua_isnil(L, -2) != 0) {
96 result += lua_tostring(L, -1);
97 result += '\n';
98 return result;
99 }
100 lua_pop(L, 1);
101 pushYue(L, "pcall"sv);
102 lua_insert(L, -2);
103 int last = lua_gettop(L) - 2;
104 if (lua_pcall(L, 1, LUA_MULTRET, 0) != 0) {
105 result = lua_tostring(L, -1);
106 result += '\n';
107 return result;
108 }
109 int cur = lua_gettop(L);
110 int retCount = cur - last;
111 bool success = lua_toboolean(L, -retCount) != 0;
112 if (success) {
113 if (retCount > 1) {
114 for (int i = 1; i < retCount; ++i) {
115 result += luaL_tolstring(L, -retCount + i, nullptr);
116 result += '\n';
117 lua_pop(L, 1);
118 }
119 }
120 } else {
121 result += lua_tostring(L, -1);
122 result += '\n';
123 }
124 return result;
125 };
126
127 execStr(R"yuescript(
128_G.__output = {}
129_G.print = (...)->
130 len = select "#", ...
131 strs = {}
132 for i = 1, len
133 strs[#strs + 1] = tostring select i, ...
134 _G.__output[#_G.__output + 1] = table.concat strs, "\n"
135 )yuescript");
136 std::string res2 = execStr(codes);
137 std::string res1 = execStr(R"yuescript(
138res = table.concat _G.__output, "\n"
139return res if res ~= ""
140 )yuescript");
141 if (res1.empty()) {
142 return res2;
143 } else {
144 if (res2.empty()) {
145 return res1;
146 } else {
147 return res1 + res2;
148 }
149 }
150}
151
152EMSCRIPTEN_BINDINGS(yue) {
153 value_array<YueResult>("YueResult")
154 .element(&YueResult::codes)
155 .element(&YueResult::err);
156 function("tolua", &tolua);
157 function("exec", &exec);
158 function("version", &version);
159}
160