NewLang Project
Yet another programm language
Loading...
Searching...
No Matches
nlc.h
Go to the documentation of this file.
1#pragma once
2#ifndef INCLUDED_NLC_
3#define INCLUDED_NLC_
4
5//#include "pch.h"
6#include <curl/curl.h>
7
8//#include <autocomplete.h>
9#include "runtime.h"
10#include "jit.h"
11
12
13// * 30.04.2021
14// * Компиляция - преобразование исходника в исполняемый файл в результет которого создается модуль динамической библиотеки.
15// * В нем содержатся экспортируемые функции, которые определены в файле и предопреденные переменные.
16// * Одна переменная - тектовая строка с исходным текстом самого файла
17// * Вторая - экспортируемая головная функция - скомпилированная последовательность шагов головного файла (игнорируя определения функций, т.к. они собраны отдельно).
18// *
19// * Выполнение такого файла - загрузка интерпретатором и либо выполнение головной функции в пакетном режиме,
20// * либо в диалоговом режиме повторная интерпретация исходного текста, пропуская определения функций (т.к. они уже скомпилированы заранее),
21// * либо вызов других функций, введенных пользователем.
22// *
23// * Выполнение обычного файла - компиляция временного файла модуля, а дальше его выполнение как предкомпилированного.
24// * Для процедуры компиляции требуется - компиляция функций, компиляция головной функции и сохранение исходного текста модуля.
25// * Для выполнение - диалоговый загрузчик, который либо загружает модуль, либо компилирует временный файл в модуль и только потом загружает.
26//
27// 14.06.2021
28// make - парсинг и компиляция функций и методов классов в отдельный модуль (nl, nlm ????)
29// load - загрузка скомпилированного модуля + вызывается call для функции с именем модуля для его инициализации, если она присутствует в модуле
30// exec - последовательное выполнение make, load и run для исходного текста программы (nlp ???)
31// eval - парсинг и выполнение текста программы в режиме интерпретатора, т.е. вызовы (call) для функций и выражений из заранее загруженных модулей
32//
33//
34// 17.02.2024
35// Концепция многократно переделывалась, и на текущйий момент она представляет сбой следующее:
36// Компилятор (исполняемый файл nlc), ядро системы которое позволет сделать действия:
37//
38// --version - версия
39// --help - помощь
40//
41// Заупстить выполнение в режиме тестовой площадки
42// --playground-cgi="format='json', port=80, memory=5, timeout=10"
43// --playground-in=""
44// ввод вывод через std::cin << >> std::cout, вывод ("Content-Type: application/json\n { \"Name\": \"Foo\", \"Id\": 1234, \"Rank\": 7 }", "Content-Type: text/plain;charset=us-ascii\n\n";
45//
46// --eval-source --eval-src - выполнить одну строку
47// --eval-file - выполнить файл
48// --make-module - создать (скомпилировать) модуль
49// --make-program --make-prg - создать (скомпилировать) приложение
50// --repl (или без аргументов ??????????????????)
51//
52// Сгенерировать исходтики на С++ для последубщей компиляции clang (в будущем)
53// --emit-cpp - генерировать исходный код
54//
55// Все параметры командрой строки передобразуются в словарь (ObjPtr) и удаляются после разбора.
56// Оставшиеся аргументы передаются в ядро системы для её инициализации.
57//
58
59namespace newlang {
60
61#define NLC_FILE_HISTORY ".nlc_history"
62
63 //
64 //#include <stdio.h>
65 //#include <wchar.h>
66 //#include <stdlib.h>
67 //#include <locale.h>
68 //
69 //int main() {
70 // int r;
71 // wchar_t myChar1 = L'Ω';
72 // setlocale(LC_CTYPE, "");
73 // r = wprintf(L"char is %lc (%x)\n", myChar1, myChar1);
74 //}
75 //
76
77 class NLC {
78 public:
79
80 enum class Mode {
81 MODE_NONE = 0,
89 REPL,
90 //
91 // Заупстить выполнение в режиме тестовой площадки
92 // --playground-cgi
93 // ввод вывод через std::cin << >> std::cout, вывод ("Content-Type: application/json\n { \"Name\": \"Foo\", \"Id\": 1234, \"Rank\": 7 }", "Content-Type: text/plain;charset=us-ascii\n\n";
94 //
95 // --eval-source --eval-src - выполнить одну строку
96 // --eval-file - выполнить файл
97 // --make-module - создать (скомпилировать) модуль
98 // --make-program --make-prg - создать (скомпилировать) приложение
99 // --repl (или без аргументов ??????????????????)
100 };
101
102
103 //#define NLC_MODE(_) \
104// _(ModeError, 0) \
105// _(ModeHelp, 1)\
106// _(ModeVersion, 2)\
107// _(ModeInter, 3)\
108// _(ModeEval, 4) \
109// _(ModeExec, 5)
110 //
111 // // _(COMPILE, 6)
112 //
113 // enum class Mode : uint8_t {
114 //#define DEFINE_ENUM(name, value) name = value,
115 // NLC_MODE(DEFINE_ENUM)
116 //#undef DEFINE_ENUM
117 // };
118 //
119 // inline const char* toString(Mode mode) {
120 //#define DEFINE_CASE(name, _) \
121// case Mode::name: \
122// return #name;
123 //
124 // switch (mode) {
125 // NLC_MODE(DEFINE_CASE)
126 // default:
127 // LOG_ERROR("UNKNOWN MODE %d", static_cast<int> (mode));
128 // return "UNKNOWN MODE";
129 // }
130 //#undef DEFINE_CASE
131 // }
132
133
135 std::string m_path; //< Имя исполняемого файла
136 // Mode m_mode; //< Режим выполнения
137 // std::vector<std::string> m_modules; //< Список модулей, которые загружаются перед выполнением
138 // std::vector<std::string> m_load_only; //< Список модулей, которые предварительно загружаются перед выполнением без инициализации
139 // bool m_no_default; //< Не загружать модуль default.src (модуль по умолчанию)
140 // std::string m_ifile; //< Имя входного файла (если есть)
141 // std::string m_ofile; //< Имя выходного файла (если есть)
142 bool m_is_silent; //< Нужно ли выводит сообщения
143 std::string m_output; //< Информация для вывода, в т.ч. при ошибке о текст подсказки
144 std::string m_eval; //< Входная информация для выполнения
145 // Context m_ctx;
147 // std::map<Obj *, ObjPtr> m_local_vars; //< Локальные переменные и объекты, которые создаются интерпретатором
148
152 std::string m_log_file_dir;
154
155 NLC() {
156 m_log_callback_save = nullptr;
157 m_log_callback_arg_save = nullptr;
158 m_log_file = nullptr;
159 }
160
161 // NLC(int argc, const char** argv) { // : m_ctx(RunTime::Init(argc, argv)) {
162 // // m_mode = Mode::ModeError;
163 // m_log_callback_save = nullptr;
164 // m_log_callback_arg_save = nullptr;
165 // m_args = RunTime::MakeTermMainArgs(argc, argv);
166 // }
167
168 // NLC(const char * str) : NLC() {
169 // std::vector<std::string> split = Macro::SplitString(str, " ");
170 // std::vector<const char *> argv;
171 // for (size_t i = 0; i < split.size(); i++) {
172 // argv.push_back(split[i].data());
173 // }
174 // ParseArgs(argv.size(), argv.data());
175 // }
176 //
177
181
182 static void LoggerCallback(void *param, Logger::LogLevelType level, const char * str, bool flush) {
183 NLC *nlc = static_cast<NLC *> (param);
184 if (nlc) {
185 nlc->m_output += str;
186 }
187 if (nlc->m_log_file) {
188 fprintf(nlc->m_log_file, "%s", str);
189 if (flush) {
190 fflush(nlc->m_log_file);
191 }
192 }
193 if (nlc && nlc->m_is_silent) {
194 return;
195 }
196 fprintf(stdout, "%s", str);
197 if (flush) {
198 fflush(stdout);
199 }
200 }
201
202 // bool ParseArgs(int64_t argc, const char** argv) {
203 //
204 // if (!argc || !argv) {
205 // m_output = "Bad args nullptr";
206 // return false;
207 // }
208 //
209 // m_args = Obj::CreateDict();
210 // for (int i = 0; i < argc; i++) {
211 // std::vector<std::string> split = Macro::SplitString(argv[i], "=");
212 // if (split.size() > 1) {
213 // m_args->push_back(Obj::CreateString(split[0]), &argv[i][split[0].size() + 1]);
214 // } else {
215 // m_args->push_back(Obj::CreateString(argv[i]));
216 // }
217 // }
218 //
219 //
220 // m_mode = Mode::ModeInter;
221 // if (argc) {
222 // m_path = argv[0];
223 // } else {
224 // m_path.clear();
225 // }
226 // m_eval.clear();
227 // m_modules.clear();
228 // m_load_only.clear();
229 // m_no_default = false;
230 // m_ifile.clear();
231 // m_ofile.clear();
232 // m_output.clear();
233 // m_is_silent = false;
234 //
235 // bool is_debug = false;
236 // bool is_help = false;
237 // bool is_ver = false;
238 // std::string load_list;
239 // std::string load_only;
240 // std::string compile;
241 // std::string exec;
242 // std::string eval;
243 //
244 // Logger::Instance()->SaveCallback(m_log_callback_save, m_log_callback_arg_save);
245 // m_loglevel_save = Logger::Instance()->GetLogLevel();
246 // Logger::Instance()->Clear();
247 // Logger::Instance()->SetCallback(&LoggerCallback, this);
248 //
249 // auto cli
250 // = lyra::help(is_help).description("Description!!!!!!!!!!!!!!!!!!")
251 // | lyra::opt(is_ver) ["-v"] ["--version"]("Version New Lang Compiler.")
252 // | lyra::opt(is_debug) ["-d"] ["--debug"]("Debug detail mode.")
253 // | lyra::opt(m_is_silent) ["-s"] ["--silent"]("Silent mode without message output.")
254 // | lyra::opt(m_ofile, "filename") ["-o"]["--output"] ("Output file name.")
255 // | lyra::opt(load_list, "list") ["-l"] ["--load"]("List of load modules.")
256 // | lyra::opt(load_only, "list") ["--load-only"]("List of load only modules (without init module after load).")
257 // | lyra::opt(compile, "filename") ["-c"] ["--compile"]("Compile input file and build NLM module.")
258 // | lyra::opt(exec, "filename") ["-x"] ["--exec"]("Compile and make module, load and eXecute main module function.")
259 // | lyra::opt(m_ifile, "filename") ["-e"] ["--eval"]("Evaluate file in interpreter mode.")
260 // | lyra::arg(m_eval, "expression") ("Evaluate expression excluding compilation.")
261 // ;
262 //
263 //
264 // auto result = cli.parse({static_cast<int> (argc), argv});
265 // if (!result) {
266 // m_mode = Mode::ModeError;
267 // m_output = result.message();
268 // return false;
269 // }
270 //
271 // if (is_debug) {
272 // Logger::Instance()->SetLogLevel(LOG_LEVEL_DEBUG);
273 // }
274 //
275 // if (is_help) {
276 // m_mode = Mode::ModeHelp;
277 // std::ostringstream out;
278 // out << cli;
279 // m_output = out.str();
280 // return true;
281 // }
282 //
283 // if (is_ver) {
284 // m_mode = Mode::ModeVersion;
285 // m_output = "Version info";
286 // return true;
287 // }
288 //
289 // m_modules = Macro::SplitString(load_list.c_str(), ",");
290 // m_load_only = Macro::SplitString(load_only.c_str(), ",");
291 //
292 //#ifdef _WIN32
293 //
294 //#else
295 // int len;
296 // char buffer[100];
297 // fcntl(STDIN_FILENO, F_SETFL, fcntl(STDIN_FILENO, F_GETFL, 0) | O_NONBLOCK);
298 // while ((len = read(STDIN_FILENO, buffer, sizeof (buffer))) > 0) {
299 // // m_eval.append(buffer, len);
300 // }
301 // fcntl(STDIN_FILENO, F_SETFL, fcntl(STDIN_FILENO, F_GETFL, 0) & ~O_NONBLOCK);
302 //#endif
303 // int cnt = 0;
304 // cnt += !compile.empty();
305 // cnt += !exec.empty();
306 // cnt += !m_ifile.empty();
307 // // cnt += !m_eval.empty();
308 //
309 // if (cnt > 1) {
310 // m_mode = Mode::ModeError;
311 // m_output = "Select only one mode: Compile, eXec or Eval!";
312 // // } else if (!compile.empty()) {
313 // // m_mode = Mode::COMPILE;
314 // // m_ifile = compile;
315 // // } else if (!exec.empty()) {
316 // // m_mode = Mode::EXEC;
317 // // m_ifile = exec;
318 // } else if (!m_eval.empty() || !m_ifile.empty()) {
319 // m_mode = Mode::ModeEval;
320 // } else {
321 // m_mode = Mode::ModeInter;
322 // }
323 //
324 // return m_mode != Mode::ModeError;
325 // }
326
327
328 //# echo "Access-Control-Allow-Origin: *"
329 //# echo "Content-type: application/json"
330 //# echo ""
331 //#
332 //# echo "{\"in\": \"$QUERY_STRING\", \"out\": \"111111111111111111\", \"stat\":\"STAT\", \"info\":\"INFO\nINFO\nINFO\nINFO\nINFO\n\"}"
333 //
334 //
335
336 static std::string url_encode(const std::string& decoded) {
337 const auto encoded_value = curl_easy_escape(nullptr, decoded.c_str(), static_cast<int> (decoded.length()));
338 std::string result(encoded_value);
339 curl_free(encoded_value);
340 return result;
341 }
342
343 static std::string url_decode(const std::string& encoded) {
344 int output_length;
345 const auto decoded_value = curl_easy_unescape(nullptr, encoded.c_str(), static_cast<int> (encoded.length()), &output_length);
346 std::string result(decoded_value, output_length);
347 curl_free(decoded_value);
348 return result;
349 }
350
351 static std::string AnswerCGI(std::string query, std::string respond) {
352
353 std::string result;
354
355 result += "{\"in\":\"";
356 result += url_encode(query);
357 result += "\",\"out\":\"";
358 result += url_encode(respond);
359 result += "\",\"version\":\"";
361 result += "\"}\n";
362
363 return result;
364 }
365
366 std::string GetHelp() {
367 // nlc [--nlc- ... ] [-h?] < -p | -c command | -m module-name | - | script > [args]
368 return "nlc [--nlc- ... ] [-h?po] <-c command | -m module-name | - | script> [main args ...]";
369 }
370
371 int Run(int argc, char** argv) {
372
373 Mode mode = Mode::MODE_NONE;
374
375 StringArray rt_args;
376 ObjPtr main_args = Obj::CreateDict();
377
378 std::string command;
379 int ret_code = 0;
380
381 bool is_playground = false;
382 std::string file_name;
383 std::string out_file;
384
385 size_t pos = 0;
386 while (++pos < argc) {
387
388 ASSERT(argv[pos]);
389 if (strcmp(argv[pos], "-v") == 0 || strcmp(argv[pos], "--version") == 0) {
390 LOG_INFO("NewLangCompiler version: %s", VERSION_SOURCE_FULL_ID);
391 return 0;
392 }
393 if (strcmp(argv[pos], "-h") == 0 || strcmp(argv[pos], "-?") == 0 || strcmp(argv[pos], "--help") == 0) {
394 LOG_INFO("%s", GetHelp().c_str());
395 return 0;
396 }
397
398
399 if (strstr(argv[pos], "--nlc-") == argv[pos]) {
400 rt_args.push_back(std::string(argv[pos]));
401 continue;
402 } else if (strcmp(argv[pos], "-p") == 0 || strcmp(argv[pos], "--playground-cgi") == 0) {
403 is_playground = true;
404 rt_args.push_back("--nlc-no-embed-source");
405 rt_args.push_back("--nlc-no-import-module");
406 rt_args.push_back("--nlc-no-import-native");
407 rt_args.push_back("--nlc-no-eval-enable");
408 continue;
409 } else if (strcmp(argv[pos], "-o") == 0 || strcmp(argv[pos], "--output") == 0) {
410 if (++pos >= argc) {
411 LOG_RUNTIME("Argument expected after '%s'", argv[pos - 1]);
412 }
413 out_file = argv[pos];
414 continue;
415 } else if (strcmp(argv[pos], "-l") == 0 || strcmp(argv[pos], "--log-dir") == 0) {
416 if (++pos >= argc) {
417 LOG_RUNTIME("Argument expected after '%s'", argv[pos - 1]);
418 }
419 m_log_file_dir = argv[pos];
420 continue;
421 }
422
423
424 if (strcmp(argv[pos], "-c") == 0 || strcmp(argv[pos], "-m") == 0 || strcmp(argv[pos], "-") == 0) {
425 if (strcmp(argv[pos++], "-") == 0) {
426 std::getline(std::cin, command);
427 } else {
428 if (pos >= argc) {
429 LOG_RUNTIME("Argument expected after '%s'", argv[pos - 1]);
430 }
431 if (strcmp(argv[pos - 1], "-m") == 0) {
432
433 if (is_playground) {
434 LOG_RUNTIME("You can't run the module in playground mode!");
435 }
436
437 file_name = argv[pos];
438 file_name += ".src";
439 main_args->push_back(Obj::CreateString(file_name));
440 } else {
441 ASSERT(strcmp(argv[pos - 1], "-c") == 0);
442 command = argv[pos];
443 main_args->push_back(Obj::CreateString(""));
444 }
445 }
446 } else {
447 // Script file name
448 file_name = argv[pos];
449 main_args->push_back(Obj::CreateString(file_name));
450 }
451
452 while (++pos < argc) {
453 main_args->push_back(Obj::CreateString(argv[pos]));
454 }
455 break;
456 }
457
458
459 if (!m_log_file_dir.empty()) {
460
461 if (!std::filesystem::exists(std::filesystem::path(m_log_file_dir))) {
462 std::filesystem::create_directories(std::filesystem::path(m_log_file_dir));
463 }
464
465 if (!std::filesystem::exists(std::filesystem::path(m_log_file_dir))) {
466 LOG_RUNTIME("The directory '%s' for log files does not exist or an error occurred while creating it!", m_log_file_dir.c_str());
467 }
468 if (!std::filesystem::is_directory(std::filesystem::path(m_log_file_dir))) {
469 LOG_RUNTIME("The file path '%s' is not a directory!", m_log_file_dir.c_str());
470 }
471
472 const std::time_t now = std::time(nullptr);
473 char filename[100];
474 std::strftime(filename, sizeof (filename), "%y%m%d_%H%M%S.log", std::localtime(&now));
475
476 m_log_file_dir += "/";
477 m_log_file_dir += filename;
478
479 m_log_file = fopen(std::filesystem::path(m_log_file_dir).c_str(), "w+");
480
481 if (!m_log_file) {
482 LOG_RUNTIME("Fail create log file '%s'!", m_log_file_dir.c_str());
483 }
484 }
485
486
487 RuntimePtr rt = RunTime::Init(rt_args);
488 JIT *jit = JIT::Init(rt);
490
491 if (is_playground) {
492
493 // playground
494
495 ASSERT(file_name.empty());
496
497 if (command.empty()) {
498 command = getenv("QUERY_STRING") ? getenv("QUERY_STRING") : "";
499 }
500
504 m_is_silent = true;
505
506 std::string header = \
507 "Content-Type: text/plain;\n"
508 "Access-Control-Allow-Origin: *\n\n";
509
510 std::ofstream f;
511
512 if (out_file.empty()) {
513 std::cout << header;
514 } else {
515 f.open(out_file);
516 if (f.fail()) {
517 LOG_RUNTIME("Fail write to file '%s'", out_file.c_str());
518 }
519 f << header;
520 }
521
522 try {
523 result = jit->Run(url_decode(command), main_args.get());
524 ret_code = 0;
525 } catch (IntAny &any) {
526 result = any.shared();
527 ret_code = 2;
528 } catch (std::exception &err) {
529 result = Obj::CreateString(err.what());
530 ret_code = 1;
531 }
532 ASSERT(result);
533
534 m_output += "\n";
535 m_output += result->toString();
536
537 m_output = AnswerCGI(command, m_output);
538
539 if (out_file.empty()) {
540 std::cout << m_output;
541 } else {
542 f << m_output;
543 if (f.fail()) {
544 LOG_RUNTIME("Fail write to file '%s'", out_file.c_str());
545 }
546 f.close();
547 }
548
549 } else if (!file_name.empty()) {
550 ASSERT(command.empty());
551 result = jit->RunFile(file_name, main_args.get());
552 } else if (!command.empty()) {
553 ASSERT(file_name.empty());
554 result = jit->Run(command, main_args.get());
555 } else {
556 ret_code = RunREPL(rt, main_args);
557 }
558
559
560 if (m_log_file) {
561 fwrite(m_output.c_str(), m_output.size(), 1, m_log_file);
562 fclose(m_log_file);
563 m_log_file = nullptr;
564 }
565
566 return ret_code;
567 }
568
569 int RunREPL(RuntimePtr rt, ObjPtr main_args) {
570
571 LOG_RUNTIME("REPL not implemented!");
572
573 return 0;
574 }
575
576
577
578 // try {
579 // //#warning EVAL
580 // // ASSERT(false);
581 // // for (auto &elem : m_load_only) {
582 // // if (!m_ctx.m_info.global->LoadModule(AddDefaultFileExt(elem.c_str(), ".nlm").c_str(), false, &m_ctx)) {
583 // // LOG_RUNTIME("Fail load-only module '%s'", AddDefaultFileExt(elem.c_str(), ".nlm").c_str());
584 // // }
585 // // }
586 // //
587 // // for (auto &elem : m_modules) {
588 // // if (!m_ctx.m_info.global->LoadModule(AddDefaultFileExt(elem.c_str(), ".nlm").c_str(), true, &m_ctx)) {
589 // // LOG_RUNTIME("Fail load or init module '%s'", AddDefaultFileExt(elem.c_str(), ".nlm").c_str());
590 // // }
591 // // }
592 //
593 // if (m_mode == Mode::ModeError || m_mode == Mode::ModeVersion || m_mode == Mode::ModeHelp) {
594 // LOG_INFO("%s", m_output.c_str());
595 // return 0;
596 // // } else if (m_mode == Mode::COMPILE || m_mode == Mode::EXEC) {
597 // //
598 // // if (m_ifile.empty()) {
599 // // LOG_RUNTIME("Empty input file!");
600 // // m_ifile = AddDefaultFileExt(m_ifile.c_str(), ".src");
601 // // }
602 // // if (m_ofile.empty()) {
603 // // m_ofile = m_ifile;
604 // // m_ofile = ReplaceFileExt(m_ofile.c_str(), ".src", ".nlm");
605 // // } else {
606 // // m_ofile = AddDefaultFileExt(m_ofile.c_str(), ".nlm");
607 // // }
608 // //
609 // // switch (m_mode) {
610 // // case Mode::COMPILE:
611 // // // if (!m_ctx.m_runtime->m_info.global->CompileModule(m_ifile.c_str(), m_ofile.c_str())) {
612 // // LOG_RUNTIME("Compile file '%s' fail!", m_ifile.c_str());
613 // // // }
614 // // break;
615 // // case Mode::EXEC:
616 // //#warning EVAL
617 // // ASSERT(false);
618 // // // ObjPtr result = NewLang::ExecModule(m_ifile.c_str(), m_ofile.c_str(), true, &m_ctx);
619 // // // m_output = result->GetValueAsString();
620 // // break;
621 // // }
622 // } else if (m_mode == Mode::ModeEval) {
623 //
624 // Obj *arg_ptr = nullptr;
625 // ObjPtr dict = Obj::CreateType(ObjType::Dictionary, ObjType::Dictionary, true);
626 // std::string source;
627 // if (!m_ifile.empty()) {
628 // source = ReadFile(m_ifile.c_str());
629 // if (source.empty()) {
630 // LOG_RUNTIME("Fail read or empty source file '%s'!", m_ifile.c_str());
631 // }
632 //
633 // if (!m_eval.empty()) {
634 // std::vector<std::string > a = Macro::SplitString(m_eval.c_str(), " ");
635 //
636 // for (int i = 0; i < a.size(); i++) {
637 // std::vector<std::string> split = Macro::SplitString(a[i].c_str(), "=");
638 // if (split.size() > 1) {
639 // dict->push_back(Obj::CreateString(split[0]), &a[i][split[0].size() + 1]);
640 // } else {
641 // dict->push_back(Obj::CreateString(a[i]));
642 // }
643 // }
644 // }
645 // arg_ptr = dict.get();
646 //
647 // } else {
648 // source = m_eval;
649 // arg_ptr = m_args.get();
650 // }
651 //
652 //
653 //
654 // ObjPtr result = m_ctx.ExecStr(source, arg_ptr, Context::CatchType::CATCH_AUTO);
655 //
656 // if (result && m_local_vars.find(result.get()) == m_local_vars.end()) {
657 // m_local_vars[result.get()] = result;
658 // }
659 //
660 // m_output = result->GetValueAsString();
661 // m_output += "\n";
662 //
663 // if (!m_ofile.empty()) {
664 // std::ofstream out(m_ofile);
665 // out << m_output;
666 // out.close();
667 // }
668 //#ifdef _WIN32
669 //
670 //#else
671 // fcntl(STDOUT_FILENO, F_SETFL, fcntl(STDOUT_FILENO, F_GETFL, 0) | O_NONBLOCK);
672 // write(STDOUT_FILENO, m_output.c_str(), m_output.size());
673 //#endif // _WIN32
674 //
675 //
676 // } else {
677 // ASSERT(m_mode == Mode::ModeInter);
678 // Interative();
679 // }
680 //
681 // } catch (Return &err) {
682 // // Вывод информации об ошибке синтаксиса при парсинге без информации о точке вызова макроса LOG_INFO
683 // Logger::LogLevelType save_level = Logger::Instance()->GetLogLevel();
684 // Logger::Instance()->SetLogLevel(LOG_LEVEL_INFO);
685 // LOG_INFO("%s", err.what());
686 // Logger::Instance()->SetLogLevel(save_level);
687 // return 1;
688 // } catch (...) {
689 // return 1;
690 // }
691 // return 0;
692 // }
693
694 // bool IsDelimiter(wchar_t c) {
695 // return c == L' ' || c == L'&' || c == L'=' || c == L';' || c == L','
696 // || c == L'+' || c == L'-' || c == L'*' || c == L'/'
697 // || c == L'<' || c == L'>' || c == L'|' || c == L'~' || c == L'^';
698 // }
699 //
700 // bool Interative() {
701 //
702 //
703 // std::string output;
704 // std::vector<std::string> history;
705 //
706 //
707 // std::ifstream infile;
708 // infile.open(NLC_FILE_HISTORY);
709 // while (infile.is_open() && getline(infile, output)) {
710 // history.push_back(output);
711 // }
712 // infile.close();
713 //
714 // std::ofstream filehistory;
715 // filehistory.open(NLC_FILE_HISTORY, std::ios::app);
716 //
717 //
718 // const char* title = ">";
719 //#ifdef _MSC_VER
720 // COLOR_TYPE title_color = 0;
721 // COLOR_TYPE predict_color = 0;
722 // COLOR_TYPE main_color = 0;
723 //#else
724 // COLOR_TYPE title_color = "1";
725 // COLOR_TYPE predict_color = "80";
726 // COLOR_TYPE main_color = "0";
727 //#endif
728 //
729 // std::wstring buff;
730 //
731 // // Cursor offset in buffer for moving
732 // int64_t offset = 0;
733 //
734 // color_print("Type ", predict_color);
739 // color_print("--", main_color);
740 // color_print("<Enter> (or ", predict_color);
741 // color_print("++", main_color);
742 // color_print("<Enter>) for exit the program.\n", predict_color);
743 //
744 // // Calculate title length
745 // int title_len = (short) strlen(title);
746 // bool show_all = false;
747 //
748 // while (1) {
749 //
750 // int64_t history_pos = history.size();
751 //
752 // while (1) {
753 // // Print title with title color
754 // clear_line();
755 // color_print(title, title_color);
756 // if (title_len) {
757 // printf(" ");
758 // }
759 //
760 // // Get length of last word in input
761 // short space_offset = 0;
762 // while (buff.size() && space_offset < buff.size() && !IsDelimiter(buff[buff.size() - space_offset - 1])) {//buff[buff.size() - space_offset - 1] != L' ') {
763 // space_offset += 1;
764 // }
765 //
766 // // Print current buffer
767 // color_print(utf8_encode(buff).c_str(), main_color);
768 //
769 // std::vector<std::wstring> predict;
770 //
771 // predict.clear();
772 // if (space_offset) {
773 // size_t overflow = 5;
774 //
775 // predict = m_ctx.m_runtime->SelectPredict(&buff[buff.size() - space_offset], overflow); // Не более 5 примеров продолжения
776 //
777 // if (predict.size()) {
778 // if (show_all) {
779 // // Показать все варинанты
780 // std::wstring helper;
781 // for (int i = 0; i < overflow; i++) {
782 // if (i >= predict.size()) {
783 // break;
784 // }
785 // if (!helper.empty()) {
786 // helper += L" ";
787 // }
788 // helper += predict[i];
789 // }
790 // if (predict.size() >= overflow) {
791 // helper += L" ..."; // и есть еще
792 // }
793 // color_print(utf8_encode(helper.substr(space_offset)).c_str(), predict_color);
794 // } else {
795 // std::wstring show(predict[0]);
796 // if (space_offset <= show.size()) {
797 // if (predict.size() > 1) { // Присутсвует более одного варианта
798 // show += L"...";
799 // }
800 // color_print(utf8_encode(show.substr(space_offset)).c_str(), predict_color);
801 // }
802 // }
803 // }
804 // }
805 //
806 // // Move cursor to edit position
807 // set_cursor_x(offset + title_len + 2);
808 //
809 // // Read character from console
810 // int ch = _getch();
811 //
812 // // LOG_DEBUG("_getch() %d", ch);
813 //
814 // int w_ch = 0;
815 //
816 // if ((ch & 0x80) && (ch != SPECIAL_SEQ_2)) {
817 //
818 // // двухбайтовые UTF8
819 // if ((ch & 0xE0) == 0xC0) {
820 // w_ch = ch & 0x1F;
821 // w_ch <<= 6;
822 // ch = _getch();
823 // w_ch |= (ch & 0x3F);
824 // } else {
825 // LOG_ERROR("Unsupported char %d", ch);
826 // w_ch = 0;
827 // }
828 // // continue;
829 //
830 // } else if (is_ignore_key(ch)) { // Wait next symbol if character in ignore keys
831 //
832 // continue;
833 //
834 // } else if (ch == KEY_ENTER) { // Return buffer if ENTER was pressed
835 //
836 // if (!buff.empty() && (history.size() == 0 || (history.size() && history[history.size() - 1].compare(utf8_encode(buff)) != 0))) {
837 // history.push_back(utf8_encode(buff));
838 // filehistory << utf8_encode(buff) << "\n";
839 // filehistory.flush();
840 // }
841 // break;
842 //
843 // }// Keyboard interrupt handler for Windows
844 //#if defined(_MSC_VER)
845 // else if (ch == CTRL_C) {
846 // goto done;
847 // }
848 //#endif
849 // // Edit buffer like backspace if BACKSPACE was pressed
850 // else if (ch == KEY_BACKSPACE || ch == 8) {
851 // if (buff.size() && offset) {
852 // // Delete character from buffer
853 // for (unsigned i = offset - 1; i < buff.size(); i++) {
854 // buff[i] = buff[i + 1];
855 // }
856 // buff.resize(buff.size() - 1);
857 // offset--;
858 // }
859 // // Apply prediction if TAB was pressed
860 // } else if (ch == KEY_TAB) {
861 //
862 // if (predict.size() == 1 || (predict.size() > 1 && show_all)) {
863 // if (space_offset < predict[0].size()) {
864 // buff.append(predict[0].substr(space_offset));
865 // }
866 // show_all = false;
867 // } else {
868 // show_all = true;
869 // }
870 // offset = buff.size();
871 //
872 // }// Arrows and Delete keys handler
873 // else if (
874 // ch == SPECIAL_SEQ
875 //#if defined(OS_WINDOWS)
876 // || ch == SPECIAL_SEQ_2 || ch == KEY_ESC
877 //#elif defined(OS_UNIX)
878 // //&& _getch()
879 //#endif
880 // //== SPECIAL_SEQ_2
881 // ) {
882 //
883 // ch = _getch();
884 //#if defined(OS_UNIX)
885 // if (ch == SPECIAL_SEQ_2) {
886 // ch = _getch(); // Skip next code
887 // } else if (ch != SPECIAL_SEQ) {
888 // continue;
889 // }
890 //#endif
891 //
892 // switch (ch) {
893 // case KEY_ESC:
894 // buff.clear();
895 // offset = 0;
896 // break;
897 // case KEY_HOME:
898 // offset = 0;
899 // break;
900 // case KEY_END:
901 // offset = buff.size();
902 // break;
903 // case KEY_LEFT:
904 // offset = (offset > 0) ? offset - 1 : 0;
905 // break;
906 // case KEY_RIGHT:
907 // // Decrease offset from the end of the buffer if left key pressed
908 // offset = (offset < static_cast<int64_t> (buff.size())) ? (offset + 1) : buff.size();
909 // break;
910 // case KEY_UP:
911 // if (!history.empty() && history_pos > 0) {
912 // clear_line();
913 // history_pos--;
914 // buff = utf8_decode(history[history_pos]);
915 // }
916 // offset = buff.size();
917 // break;
918 // case KEY_DOWN:
919 // if (!history.empty() && history_pos + 1 < static_cast<int64_t> (history.size())) {
920 // clear_line();
921 // history_pos++;
922 // buff = utf8_decode(history[history_pos]);
923 // }
924 // offset = buff.size();
925 // break;
926 // case KEY_DEL: // Edit buffer like DELETE key
927 //#if defined(OS_UNIX)
928 // if (_getch() == KEY_DEL_AFTER)
929 //#endif
930 // {
931 // if (buff.size() && offset < buff.size()) {
932 // // Delete character from buffer
933 // for (unsigned i = offset; i < buff.size() - 1; i++) {
934 // buff[i] = buff[i + 1];
935 // }
936 // buff.resize(buff.size() - 1);
937 // }
938 // }
939 // break;
940 // default:
941 // break;
942 // }
943 //
944 // } else {
945 // // Ascii char
946 // w_ch = ch;
947 // }
948 //
949 // if (w_ch) {
950 // buff.insert(offset, 1, w_ch);
951 // offset++;
952 // }
953 // }
954 //
955 //
956 // std::wstring result;
957 // if (buff.compare(L"--") == 0 || buff.compare(L"--;") == 0 || buff.compare(L"++") == 0 || buff.compare(L"++;") == 0) {
958 // printf("\n");
959 // break;
960 // } else if (!buff.empty()) {
961 // try {
962 // std::wstring input = buff;
963 //
964 // ObjPtr res = m_ctx.ExecStr(utf8_encode(input), m_args.get(), Context::CatchType::CATCH_ALL);
965 //
966 // if (res) {
967 //
968 // if (m_local_vars.find(res.get()) == m_local_vars.end()) {
969 // m_local_vars[res.get()] = res;
970 // }
971 //
972 // result = res->GetValueAsStringWide();
973 // } else {
974 // result = L"nullptr";
975 // }
976 //
977 // } catch (std::exception &err) {
978 // result = utf8_decode(err.what());
979 // }
980 // buff.clear();
981 // }
982 // printf("\n%ls\n", result.c_str());
983 // show_all = false;
984 // offset = 0;
985 // }
986 //
987 //#if defined(_MSC_VER)
988 //done:
989 //#endif
990 //
991 // filehistory.close();
992 // return 0;
993 // }
994
995 };
996
997}
998
999#endif // INCLUDED_NLC_
ObjPtr Run(const std::string_view str, Obj *args=nullptr)
Definition jit.cpp:2558
ObjPtr RunFile(std::string file, Obj *args=nullptr)
Definition jit.cpp:2540
void FuncCallback(void *param, LogLevelType level, const char *str, bool flush)
Definition logger.h:320
void SetCallback(FuncCallback *func, void *param)
Definition logger.h:358
uint8_t LogLevelType
Definition logger.h:319
LogLevelType GetLogLevel()
Definition logger.h:322
void SaveCallback(FuncCallback *&func, void *&param)
Definition logger.h:363
static Logger * Instance()
Definition logger.h:377
Logger::FuncCallback * m_log_callback_save
Definition nlc.h:150
static std::string AnswerCGI(std::string query, std::string respond)
Definition nlc.h:351
std::string GetHelp()
Definition nlc.h:366
int RunREPL(RuntimePtr rt, ObjPtr main_args)
Definition nlc.h:569
TermPtr m_args
Definition nlc.h:146
virtual ~NLC()
Definition nlc.h:178
bool m_is_silent
Definition nlc.h:142
bool is_emit_cpp
Definition nlc.h:134
std::string m_path
Definition nlc.h:135
std::string m_eval
Definition nlc.h:144
std::string m_output
Definition nlc.h:143
FILE * m_log_file
Definition nlc.h:153
static std::string url_decode(const std::string &encoded)
Definition nlc.h:343
static std::string url_encode(const std::string &decoded)
Definition nlc.h:336
std::string m_log_file_dir
Definition nlc.h:152
static void LoggerCallback(void *param, Logger::LogLevelType level, const char *str, bool flush)
Definition nlc.h:182
int Run(int argc, char **argv)
Definition nlc.h:371
Logger::LogLevelType m_loglevel_save
Definition nlc.h:149
void * m_log_callback_arg_save
Definition nlc.h:151
static ObjPtr CreateString(const std::string_view str, Sync *sync=nullptr)
Definition object.h:1596
ObjPtr shared()
Definition object.h:389
static ObjPtr CreateDict(Sync *sync=nullptr)
Definition object.h:1625
static RuntimePtr Init(StringArray args)
Definition runtime.cpp:1222
int result
Definition lexer.l:367
#define LOG_RUNTIME(format,...)
Definition logger.h:26
#define LOG_INFO(...)
Definition logger.h:120
#define ASSERT(condition)
Definition logger.h:60
Definition nlc.h:59
std::shared_ptr< Term > TermPtr
Definition variable.h:33
std::shared_ptr< Obj > ObjPtr
Definition variable.h:28
std::shared_ptr< RunTime > RuntimePtr
Definition types.h:242
std::vector< std::string > StringArray
Definition types.h:148
#define VERSION_SOURCE_FULL_ID
Definition version.h:7