aboutsummaryrefslogtreecommitdiff
path: root/src/moonp.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/moonp.cpp')
-rw-r--r--src/moonp.cpp180
1 files changed, 40 insertions, 140 deletions
diff --git a/src/moonp.cpp b/src/moonp.cpp
index a4bc1fa..a43f11c 100644
--- a/src/moonp.cpp
+++ b/src/moonp.cpp
@@ -10,10 +10,25 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
10#include <fstream> 10#include <fstream>
11#include <chrono> 11#include <chrono>
12#include <future> 12#include <future>
13#include <sstream>
14#include <tuple>
13#include "MoonP/moon_compiler.h" 15#include "MoonP/moon_compiler.h"
14#include "MoonP/moon_parser.h" 16#include "MoonP/moon_parser.h"
15 17
16#ifndef LIBMOONP 18extern "C" {
19
20#include "lua.h"
21#include "lauxlib.h"
22#include "lualib.h"
23int luaopen_moonp(lua_State* L);
24
25} // extern "C"
26
27static void openlibs(void* state) {
28 lua_State* L = static_cast<lua_State*>(state);
29 luaL_openlibs(L);
30 luaopen_moonp(L);
31}
17 32
18int main(int narg, const char** args) { 33int main(int narg, const char** args) {
19 const char* help = 34 const char* help =
@@ -81,7 +96,7 @@ int main(int narg, const char** args) {
81 if (!targetPath.empty() && targetPath.back() != '/' && targetPath.back() != '\\') { 96 if (!targetPath.empty() && targetPath.back() != '/' && targetPath.back() != '\\') {
82 targetPath.append("/"); 97 targetPath.append("/");
83 } 98 }
84 std::list<std::future<int>> results; 99 std::list<std::future<std::pair<int,std::string>>> results;
85 for (const auto& file : files) { 100 for (const auto& file : files) {
86 auto task = std::async(std::launch::async, [=]() { 101 auto task = std::async(std::launch::async, [=]() {
87 std::ifstream input(file, std::ios::in); 102 std::ifstream input(file, std::ios::in);
@@ -91,7 +106,7 @@ int main(int narg, const char** args) {
91 std::istreambuf_iterator<char>()); 106 std::istreambuf_iterator<char>());
92 if (dumpCompileTime) { 107 if (dumpCompileTime) {
93 auto start = std::chrono::high_resolution_clock::now(); 108 auto start = std::chrono::high_resolution_clock::now();
94 auto result = MoonP::MoonCompiler{}.compile(s, config); 109 auto result = MoonP::MoonCompiler{nullptr,openlibs}.compile(s, config);
95 auto end = std::chrono::high_resolution_clock::now(); 110 auto end = std::chrono::high_resolution_clock::now();
96 if (!std::get<0>(result).empty()) { 111 if (!std::get<0>(result).empty()) {
97 std::chrono::duration<double> diff = end - start; 112 std::chrono::duration<double> diff = end - start;
@@ -99,21 +114,22 @@ int main(int narg, const char** args) {
99 MoonP::MoonParser{}.parse<MoonP::File_t>(s); 114 MoonP::MoonParser{}.parse<MoonP::File_t>(s);
100 end = std::chrono::high_resolution_clock::now(); 115 end = std::chrono::high_resolution_clock::now();
101 std::chrono::duration<double> parseDiff = end - start; 116 std::chrono::duration<double> parseDiff = end - start;
102 std::cout << file << " \n"; 117 std::ostringstream buf;
103 std::cout << "Parse time: " << std::setprecision(5) << parseDiff.count() * 1000 << " ms\n"; 118 buf << file << " \n";
104 std::cout << "Compile time: " << std::setprecision(5) << (diff.count() - parseDiff.count()) * 1000 << " ms\n\n"; 119 buf << "Parse time: " << std::setprecision(5) << parseDiff.count() * 1000 << " ms\n";
105 return 0; 120 buf << "Compile time: " << std::setprecision(5) << (diff.count() - parseDiff.count()) * 1000 << " ms\n\n";
121 return std::pair{0, buf.str()};
106 } else { 122 } else {
107 std::cout << "Fail to compile: " << file << ".\n"; 123 std::ostringstream buf;
108 std::cout << std::get<1>(result) << '\n'; 124 buf << "Fail to compile: " << file << ".\n";
109 return 1; 125 buf << std::get<1>(result) << '\n';
126 return std::pair{1, buf.str()};
110 } 127 }
111 } 128 }
112 auto result = MoonP::MoonCompiler{}.compile(s, config); 129 auto result = MoonP::MoonCompiler{nullptr,openlibs}.compile(s, config);
113 if (!std::get<0>(result).empty()) { 130 if (!std::get<0>(result).empty()) {
114 if (!writeToFile) { 131 if (!writeToFile) {
115 std::cout << std::get<0>(result) << '\n'; 132 return std::pair{1, std::get<0>(result) + '\n'};
116 return 1;
117 } else { 133 } else {
118 std::string targetFile; 134 std::string targetFile;
119 if (resultFile.empty()) { 135 if (resultFile.empty()) {
@@ -139,149 +155,33 @@ int main(int narg, const char** args) {
139 if (output) { 155 if (output) {
140 const auto& codes = std::get<0>(result); 156 const auto& codes = std::get<0>(result);
141 output.write(codes.c_str(), codes.size()); 157 output.write(codes.c_str(), codes.size());
142 std::cout << "Built " << file << '\n'; 158 return std::pair{0, std::string("Built ") + file + '\n'};
143 return 0;
144 } else { 159 } else {
145 std::cout << "Fail to write file: " << targetFile << ".\n"; 160 return std::pair{1, std::string("Fail to write file: ") + targetFile + '\n'};
146 return 1;
147 } 161 }
148 } 162 }
149 } else { 163 } else {
150 std::cout << "Fail to compile: " << file << ".\n"; 164 std::ostringstream buf;
151 std::cout << std::get<1>(result) << '\n'; 165 buf << "Fail to compile: " << file << ".\n";
152 return 1; 166 buf << std::get<1>(result) << '\n';
167 return std::pair{1, buf.str()};
153 } 168 }
154 } else { 169 } else {
155 std::cout << "Fail to read file: " << file << ".\n"; 170 return std::pair{1, std::string("Fail to read file: ") + file + ".\n"};
156 return 1;
157 } 171 }
158 }); 172 });
159 results.push_back(std::move(task)); 173 results.push_back(std::move(task));
160 } 174 }
161 int ret = 0; 175 int ret = 0;
176 std::string msg;
162 for (auto& result : results) { 177 for (auto& result : results) {
163 int val = result.get(); 178 int val = 0;
179 std::tie(val, msg) = result.get();
164 if (val != 0) { 180 if (val != 0) {
165 ret = val; 181 ret = val;
166 } 182 }
183 std::cout << msg;
167 } 184 }
168 return ret; 185 return ret;
169} 186}
170 187
171#else
172
173extern "C" {
174
175#include "lua.h"
176#include "lauxlib.h"
177
178static const char moonplusCodes[] =
179#include "Moonscript.h"
180
181static int init_moonplus(lua_State* L) {
182 MoonP::MoonConfig config;
183 std::string s(moonplusCodes, sizeof(moonplusCodes) / sizeof(moonplusCodes[0]) - 1);
184 std::string codes, err;
185 MoonP::GlobalVars globals;
186 std::tie(codes, err, globals) = MoonP::MoonCompiler{}.compile(s, config);
187 if (codes.empty()) {
188 luaL_error(L, "fail to compile moonplus init codes.\n%s", err.c_str());
189 }
190 int top = lua_gettop(L);
191 if (luaL_loadbuffer(L, codes.c_str(), codes.size(), "=(moonplus)") != 0) {
192 luaL_error(L, "fail to init moonplus module.");
193 } else {
194 lua_call(L, 0, 0);
195 }
196 lua_settop(L, top);
197 return 0;
198}
199
200static const char stpCodes[] =
201#include "StackTracePlus.h"
202
203static int init_stacktraceplus(lua_State* L) {
204 if (luaL_loadbuffer(L, stpCodes, sizeof(stpCodes) / sizeof(stpCodes[0]) - 1, "=(stacktraceplus)") != 0) {
205 luaL_error(L, "fail to init stacktraceplus module.");
206 } else {
207 lua_call(L, 0, 1);
208 }
209 return 1;
210}
211
212static int moontolua(lua_State* L) {
213 size_t size = 0;
214 const char* input = luaL_checklstring(L, 1, &size);
215 MoonP::MoonConfig config;
216 if (lua_gettop(L) == 2) {
217 lua_pushstring(L, "lint_global");
218 lua_gettable(L, -2);
219 if (!lua_isnil(L, -1)) {
220 config.lintGlobalVariable = lua_toboolean(L, -1) != 0;
221 }
222 lua_pop(L, 1);
223 lua_pushstring(L, "implicit_return_root");
224 lua_gettable(L, -2);
225 if (!lua_isnil(L, -1)) {
226 config.implicitReturnRoot = lua_toboolean(L, -1) != 0;
227 }
228 lua_pop(L, 1);
229 lua_pushstring(L, "reserve_line_number");
230 lua_gettable(L, -2);
231 if (!lua_isnil(L, -1)) {
232 config.reserveLineNumber = lua_toboolean(L, -1) != 0;
233 }
234 lua_pop(L, 1);
235 }
236 std::string s(input, size);
237 std::string codes, err;
238 MoonP::GlobalVars globals;
239 std::tie(codes, err, globals) = MoonP::MoonCompiler{}.compile(s, config);
240 if (codes.empty()) {
241 lua_pushnil(L);
242 } else {
243 lua_pushlstring(L, codes.c_str(), codes.size());
244 }
245 if (err.empty()) {
246 lua_pushnil(L);
247 } else {
248 lua_pushlstring(L, err.c_str(), err.size());
249 }
250 if (globals) {
251 lua_createtable(L, static_cast<int>(globals->size()), 0);
252 int i = 1;
253 for (const auto& var : *globals) {
254 lua_createtable(L, 3, 0);
255 lua_pushlstring(L, var.name.c_str(), var.name.size());
256 lua_rawseti(L, -2, 1);
257 lua_pushinteger(L, var.line);
258 lua_rawseti(L, -2, 2);
259 lua_pushinteger(L, var.col);
260 lua_rawseti(L, -2, 3);
261 lua_rawseti(L, -2, i);
262 i++;
263 }
264 } else {
265 lua_pushnil(L);
266 }
267 return 3;
268}
269
270int luaopen_moonp(lua_State* L) {
271 lua_getglobal(L, "package");
272 lua_getfield(L, -1, "loaded");
273 lua_createtable(L, 0, 0);
274 lua_pushcfunction(L, moontolua);
275 lua_setfield(L, -2, "to_lua");
276 lua_pushcfunction(L, init_stacktraceplus);
277 lua_setfield(L, -2, "load_stacktraceplus");
278 lua_setfield(L, -2, "moonp");
279 lua_pop(L, 2);
280 init_moonplus(L);
281 return 0;
282}
283
284} // extern "C"
285
286#endif // LIBMOONP
287