aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLi Jin <dragon-fly@qq.com>2020-03-24 18:09:45 +0800
committerLi Jin <dragon-fly@qq.com>2020-03-24 18:09:45 +0800
commitd04b23b9a47c2ec6631aec16dc79f5b803fe07f3 (patch)
treedd851ebf0499b6acca5b6962207094f48eb6c414
parent2447d158241aeaaf9c0b1ab21a08db7a40e5cef3 (diff)
downloadyuescript-d04b23b9a47c2ec6631aec16dc79f5b803fe07f3.tar.gz
yuescript-d04b23b9a47c2ec6631aec16dc79f5b803fe07f3.tar.bz2
yuescript-d04b23b9a47c2ec6631aec16dc79f5b803fe07f3.zip
add command line option "-e" to moonp to eval file or string.
-rw-r--r--makefile2
-rw-r--r--src/moonp.cpp209
2 files changed, 157 insertions, 54 deletions
diff --git a/makefile b/makefile
index 68f35be..a285842 100644
--- a/makefile
+++ b/makefile
@@ -210,7 +210,7 @@ clean:
210test: release 210test: release
211 @echo "Compiling Moonscript codes..." 211 @echo "Compiling Moonscript codes..."
212 @$(START_TIME) 212 @$(START_TIME)
213 @./$(BIN_NAME) $(TEST_INPUT)/*.moon -t $(TEST_OUTPUT) 213 @./$(BIN_NAME) $(TEST_INPUT) -t $(TEST_OUTPUT)
214 @echo -en "Compile time: " 214 @echo -en "Compile time: "
215 @$(END_TIME) 215 @$(END_TIME)
216 216
diff --git a/src/moonp.cpp b/src/moonp.cpp
index a43f11c..4128f10 100644
--- a/src/moonp.cpp
+++ b/src/moonp.cpp
@@ -5,6 +5,10 @@ Permission is hereby granted, free of charge, to any person obtaining a copy of
5The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 5The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 6
7THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 7THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
8
9#include "MoonP/moon_compiler.h"
10#include "MoonP/moon_parser.h"
11
8#include <iostream> 12#include <iostream>
9#include <iomanip> 13#include <iomanip>
10#include <fstream> 14#include <fstream>
@@ -12,8 +16,14 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
12#include <future> 16#include <future>
13#include <sstream> 17#include <sstream>
14#include <tuple> 18#include <tuple>
15#include "MoonP/moon_compiler.h" 19#include <string_view>
16#include "MoonP/moon_parser.h" 20#include <memory>
21using namespace std::string_view_literals;
22#include <filesystem>
23namespace fs = std::filesystem;
24
25#define _DEFER(code,line) std::shared_ptr<void> _defer_##line(nullptr, [&](auto){code;})
26#define DEFER(code) _DEFER(code,__LINE__)
17 27
18extern "C" { 28extern "C" {
19 29
@@ -30,16 +40,29 @@ static void openlibs(void* state) {
30 luaopen_moonp(L); 40 luaopen_moonp(L);
31} 41}
32 42
43void pushMoonp(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, "moonp"); // package loaded moonp
47 lua_pushlstring(L, &name.front(), name.size()); // package loaded moonp name
48 lua_gettable(L, -2); // loaded[name], package loaded moonp item
49 lua_insert(L, -4); // item package loaded moonp
50 lua_pop(L, 3); // item
51}
52
33int main(int narg, const char** args) { 53int main(int narg, const char** args) {
34 const char* help = 54 const char* help =
35"Usage: moonp [options|files] ...\n\n" 55"Usage: moonp [options|files|directories] ...\n\n"
36" -h Print this message\n" 56" -h Print this message\n"
37" -t path Specify where to place compiled files\n" 57" -e str Execute a file or raw codes\n"
38" -o file Write output to file\n" 58" -t path Specify where to place compiled files\n"
39" -p Write output to standard out\n" 59" -o file Write output to file\n"
40" -b Dump compile time (doesn't write output)\n" 60" -p Write output to standard out\n"
41" -l Write line numbers from source codes\n" 61" -b Dump compile time (doesn't write output)\n"
42" -v Print version\n"; 62" -l Write line numbers from source codes\n"
63" -v Print version\n"
64" -- Read from standard in, print to standard out\n"
65" (Must be first and only argument)\n";
43 if (narg == 0) { 66 if (narg == 0) {
44 std::cout << help; 67 std::cout << help;
45 return 0; 68 return 0;
@@ -50,14 +73,88 @@ int main(int narg, const char** args) {
50 bool dumpCompileTime = false; 73 bool dumpCompileTime = false;
51 std::string targetPath; 74 std::string targetPath;
52 std::string resultFile; 75 std::string resultFile;
53 std::list<std::string> files; 76 std::list<std::pair<std::string,std::string>> files;
54 for (int i = 1; i < narg; ++i) { 77 for (int i = 1; i < narg; ++i) {
55 std::string arg = args[i]; 78 std::string arg = args[i];
56 if (arg == "-l") { 79 if (arg == "--"sv) {
80 if (i != 1) {
81 std::cout << help;
82 return 1;
83 }
84 char ch;
85 std::string s;
86 while ((ch = std::cin.get()) != EOF) {
87 s += ch;
88 }
89 MoonP::MoonConfig conf;
90 conf.implicitReturnRoot = true;
91 conf.lintGlobalVariable = false;
92 conf.reserveLineNumber = false;
93 auto result = MoonP::MoonCompiler{nullptr, openlibs}.compile(s, conf);
94 if (std::get<1>(result).empty()) {
95 std::cout << std::get<0>(result);
96 return 0;
97 } else {
98 std::ostringstream buf;
99 std::cout << std::get<1>(result) << '\n';
100 return 1;
101 }
102 } else if (arg == "-e"sv) {
103 ++i;
104 if (i < narg) {
105 lua_State* L = luaL_newstate();
106 openlibs(L);
107 DEFER(lua_close(L));
108 pushMoonp(L, "insert_loader"sv);
109 if (lua_pcall(L, 0, 0, 0) != 0) {
110 std::cout << lua_tostring(L, -1) << '\n';
111 return 1;
112 }
113 std::string evalStr = args[i];
114 std::ifstream input(evalStr, std::ios::in);
115 if (input) {
116 auto ext = fs::path(evalStr).extension().string();
117 for (auto& ch : ext) ch = std::tolower(ch);
118 if (ext == ".lua") {
119 lua_getglobal(L, "load");
120 } else {
121 pushMoonp(L, "loadstring"sv);
122 }
123 std::string s(
124 (std::istreambuf_iterator<char>(input)),
125 std::istreambuf_iterator<char>());
126 lua_pushlstring(L, s.c_str(), s.size());
127 lua_pushlstring(L, evalStr.c_str(), evalStr.size());
128 } else {
129 pushMoonp(L, "loadstring"sv);
130 lua_pushlstring(L, evalStr.c_str(), evalStr.size());
131 lua_pushliteral(L, "=(eval str)");
132 }
133 if (lua_pcall(L, 2, 1, 0) != 0) {
134 std::cout << lua_tostring(L, -1) << '\n';
135 return 1;
136 }
137 pushMoonp(L, "pcall"sv);
138 lua_insert(L, -2);
139 if (lua_pcall(L, 1, 2, 0) != 0) {
140 std::cout << lua_tostring(L, -1) << '\n';
141 return 1;
142 }
143 bool success = lua_toboolean(L, -2) != 0;
144 if (!success) {
145 std::cout << lua_tostring(L, -1) << '\n';
146 return 1;
147 }
148 return 0;
149 } else {
150 std::cout << help;
151 return 1;
152 }
153 } else if (arg == "-l"sv) {
57 config.reserveLineNumber = true; 154 config.reserveLineNumber = true;
58 } else if (arg == "-p") { 155 } else if (arg == "-p"sv) {
59 writeToFile = false; 156 writeToFile = false;
60 } else if (arg == "-t") { 157 } else if (arg == "-t"sv) {
61 ++i; 158 ++i;
62 if (i < narg) { 159 if (i < narg) {
63 targetPath = args[i]; 160 targetPath = args[i];
@@ -65,15 +162,15 @@ int main(int narg, const char** args) {
65 std::cout << help; 162 std::cout << help;
66 return 1; 163 return 1;
67 } 164 }
68 } else if (arg == "-b") { 165 } else if (arg == "-b"sv) {
69 dumpCompileTime = true; 166 dumpCompileTime = true;
70 } else if (arg == "-h") { 167 } else if (arg == "-h"sv) {
71 std::cout << help; 168 std::cout << help;
72 return 0; 169 return 0;
73 } else if (arg == "-v") { 170 } else if (arg == "-v"sv) {
74 std::cout << "Moonscript version: " << MoonP::moonScriptVersion() << '\n'; 171 std::cout << "Moonscript version: "sv << MoonP::moonScriptVersion() << '\n';
75 return 0; 172 return 0;
76 } else if (arg == "-o") { 173 } else if (arg == "-o"sv) {
77 ++i; 174 ++i;
78 if (i < narg) { 175 if (i < narg) {
79 resultFile = args[i]; 176 resultFile = args[i];
@@ -82,7 +179,19 @@ int main(int narg, const char** args) {
82 return 1; 179 return 1;
83 } 180 }
84 } else { 181 } else {
85 files.push_back(arg); 182 if (fs::is_directory(arg)) {
183 for (auto item : fs::recursive_directory_iterator(arg)) {
184 if (!item.is_directory()) {
185 auto ext = item.path().extension().string();
186 for (char& ch : ext) ch = std::tolower(ch);
187 if (ext == ".moon"sv) {
188 files.emplace_back(item.path().string(), item.path().lexically_relative(arg).string());
189 }
190 }
191 }
192 } else {
193 files.emplace_back(arg, arg);
194 }
86 } 195 }
87 } 196 }
88 if (files.empty()) { 197 if (files.empty()) {
@@ -90,23 +199,20 @@ int main(int narg, const char** args) {
90 return 0; 199 return 0;
91 } 200 }
92 if (!resultFile.empty() && files.size() > 1) { 201 if (!resultFile.empty() && files.size() > 1) {
93 std::cout << "Error: -o can not be used with multiple input files.\n"; 202 std::cout << "Error: -o can not be used with multiple input files.\n"sv;
94 std::cout << help; 203 std::cout << help;
95 } 204 }
96 if (!targetPath.empty() && targetPath.back() != '/' && targetPath.back() != '\\') {
97 targetPath.append("/");
98 }
99 std::list<std::future<std::pair<int,std::string>>> results; 205 std::list<std::future<std::pair<int,std::string>>> results;
100 for (const auto& file : files) { 206 for (const auto& file : files) {
101 auto task = std::async(std::launch::async, [=]() { 207 auto task = std::async(std::launch::async, [=]() {
102 std::ifstream input(file, std::ios::in); 208 std::ifstream input(file.first, std::ios::in);
103 if (input) { 209 if (input) {
104 std::string s( 210 std::string s(
105 (std::istreambuf_iterator<char>(input)), 211 (std::istreambuf_iterator<char>(input)),
106 std::istreambuf_iterator<char>()); 212 std::istreambuf_iterator<char>());
107 if (dumpCompileTime) { 213 if (dumpCompileTime) {
108 auto start = std::chrono::high_resolution_clock::now(); 214 auto start = std::chrono::high_resolution_clock::now();
109 auto result = MoonP::MoonCompiler{nullptr,openlibs}.compile(s, config); 215 auto result = MoonP::MoonCompiler{nullptr, openlibs}.compile(s, config);
110 auto end = std::chrono::high_resolution_clock::now(); 216 auto end = std::chrono::high_resolution_clock::now();
111 if (!std::get<0>(result).empty()) { 217 if (!std::get<0>(result).empty()) {
112 std::chrono::duration<double> diff = end - start; 218 std::chrono::duration<double> diff = end - start;
@@ -115,59 +221,57 @@ int main(int narg, const char** args) {
115 end = std::chrono::high_resolution_clock::now(); 221 end = std::chrono::high_resolution_clock::now();
116 std::chrono::duration<double> parseDiff = end - start; 222 std::chrono::duration<double> parseDiff = end - start;
117 std::ostringstream buf; 223 std::ostringstream buf;
118 buf << file << " \n"; 224 buf << file.first << " \n"sv;
119 buf << "Parse time: " << std::setprecision(5) << parseDiff.count() * 1000 << " ms\n"; 225 buf << "Parse time: "sv << std::setprecision(5) << parseDiff.count() * 1000 << " ms\n";
120 buf << "Compile time: " << std::setprecision(5) << (diff.count() - parseDiff.count()) * 1000 << " ms\n\n"; 226 buf << "Compile time: "sv << std::setprecision(5) << (diff.count() - parseDiff.count()) * 1000 << " ms\n\n";
121 return std::pair{0, buf.str()}; 227 return std::pair{0, buf.str()};
122 } else { 228 } else {
123 std::ostringstream buf; 229 std::ostringstream buf;
124 buf << "Fail to compile: " << file << ".\n"; 230 buf << "Fail to compile: "sv << file.first << ".\n"sv;
125 buf << std::get<1>(result) << '\n'; 231 buf << std::get<1>(result) << '\n';
126 return std::pair{1, buf.str()}; 232 return std::pair{1, buf.str()};
127 } 233 }
128 } 234 }
129 auto result = MoonP::MoonCompiler{nullptr,openlibs}.compile(s, config); 235 auto result = MoonP::MoonCompiler{nullptr, openlibs}.compile(s, config);
130 if (!std::get<0>(result).empty()) { 236 if (!std::get<0>(result).empty()) {
131 if (!writeToFile) { 237 if (!writeToFile) {
132 return std::pair{1, std::get<0>(result) + '\n'}; 238 return std::pair{1, std::get<0>(result) + '\n'};
133 } else { 239 } else {
134 std::string targetFile; 240 fs::path targetFile;
135 if (resultFile.empty()) { 241 if (!resultFile.empty()) {
136 targetFile = file; 242 targetFile = resultFile;
137 size_t pos = file.rfind('.'); 243 } else {
138 if (pos != std::string::npos) {
139 targetFile = file.substr(0, pos) + ".lua";
140 }
141 if (!targetPath.empty()) { 244 if (!targetPath.empty()) {
142 std::string name; 245 targetFile = fs::path(targetPath) / file.second;
143 pos = targetFile.find_last_of("/\\"); 246 } else {
144 if (pos == std::string::npos) { 247 targetFile = file.first;
145 name = targetFile;
146 } else {
147 name = targetFile.substr(pos + 1);
148 }
149 targetFile = targetPath + name;
150 } 248 }
151 } else { 249 targetFile.replace_extension(".lua"sv);
152 targetFile = resultFile; 250 }
251 if (!targetPath.empty()) {
252 fs::create_directories(targetFile.parent_path());
153 } 253 }
154 std::ofstream output(targetFile, std::ios::trunc | std::ios::out); 254 std::ofstream output(targetFile, std::ios::trunc | std::ios::out);
155 if (output) { 255 if (output) {
156 const auto& codes = std::get<0>(result); 256 const auto& codes = std::get<0>(result);
257 if (config.reserveLineNumber) {
258 auto head = std::string("-- [moon]: "sv) + file.first + '\n';
259 output.write(head.c_str(), head.size());
260 }
157 output.write(codes.c_str(), codes.size()); 261 output.write(codes.c_str(), codes.size());
158 return std::pair{0, std::string("Built ") + file + '\n'}; 262 return std::pair{0, std::string("Built "sv) + file.first + '\n'};
159 } else { 263 } else {
160 return std::pair{1, std::string("Fail to write file: ") + targetFile + '\n'}; 264 return std::pair{1, std::string("Fail to write file: "sv) + targetFile.string() + '\n'};
161 } 265 }
162 } 266 }
163 } else { 267 } else {
164 std::ostringstream buf; 268 std::ostringstream buf;
165 buf << "Fail to compile: " << file << ".\n"; 269 buf << "Fail to compile: "sv << file.first << ".\n";
166 buf << std::get<1>(result) << '\n'; 270 buf << std::get<1>(result) << '\n';
167 return std::pair{1, buf.str()}; 271 return std::pair{1, buf.str()};
168 } 272 }
169 } else { 273 } else {
170 return std::pair{1, std::string("Fail to read file: ") + file + ".\n"}; 274 return std::pair{1, std::string("Fail to read file: "sv) + file.first + ".\n"};
171 } 275 }
172 }); 276 });
173 results.push_back(std::move(task)); 277 results.push_back(std::move(task));
@@ -184,4 +288,3 @@ int main(int narg, const char** args) {
184 } 288 }
185 return ret; 289 return ret;
186} 290}
187