NewLang Project
Yet another programm language
Loading...
Searching...
No Matches
jit.cpp
Go to the documentation of this file.
1
2#include "warning_push.h"
3
4#include <clang/AST/ASTConcept.h>
5#include <clang/Sema/SemaConcept.h>
6#include <clang/Driver/Driver.h>
7#include <clang/Driver/Compilation.h>
8
9#include <llvm/IR/LegacyPassManager.h>
10#include <llvm/MC/TargetRegistry.h>
11#include <llvm/Support/CodeGen.h>
12
13#include <llvm/Support/Signals.h>
14
15#include <llvm/Analysis/AliasAnalysis.h>
16#include <clang/Frontend/TextDiagnosticPrinter.h>
17
18#include "warning_pop.h"
19
20#include "jit.h"
21#include "runtime.h"
22#include "term.h"
23#include "analysis.h"
24#include "module.h"
25
26#include "build_options.data"
27#include "include_h_i.data"
28
29//inline constexpr unsigned long newlang_build_options_size = 30;
30//inline std::string newlang_build_options_arr[newlang_build_options_size];
31//inline constexpr unsigned long newlang_include_h_i_size = 111295;
32//inline std::string newlang_include_h_i_arr[newlang_include_h_i_size]
33
34
35
36using namespace newlang;
37
38JIT * JIT::m_instance = nullptr;
39
40//LLVMBuilderRef RunTime::m_llvm_builder = nullptr;
41//LLVMModuleRef RunTime::m_llvm_module = nullptr;
42//LLVMExecutionEngineRef RunTime::m_llvm_engine = nullptr;
43
44bool newlang::Tranliterate(const wchar_t c, std::wstring &str) {
45 switch (c) {
46 case L'а': str.append(L"a");
47 return true;
48 case L'б': str.append(L"b");
49 return true;
50 case L'в': str.append(L"v");
51 return true;
52 case L'г': str.append(L"g");
53 return true;
54 case L'д': str.append(L"d");
55 return true;
56 case L'е': str.append(L"e");
57 return true;
58 case L'ё': str.append(L"ye");
59 return true;
60 case L'ж': str.append(L"zh");
61 return true;
62 case L'з': str.append(L"z");
63 return true;
64 case L'и': str.append(L"i");
65 return true;
66 case L'й': str.append(L"y");
67 return true;
68 case L'к': str.append(L"k");
69 return true;
70 case L'л': str.append(L"l");
71 return true;
72 case L'м': str.append(L"m");
73 return true;
74 case L'н': str.append(L"n");
75 return true;
76 case L'о': str.append(L"o");
77 return true;
78 case L'п': str.append(L"p");
79 return true;
80 case L'р': str.append(L"r");
81 return true;
82 case L'с': str.append(L"s");
83 return true;
84 case L'т': str.append(L"t");
85 return true;
86 case L'у': str.append(L"u");
87 return true;
88 case L'ф': str.append(L"f");
89 return true;
90 case L'х': str.append(L"h");
91 return true;
92 case L'ц': str.append(L"z");
93 return true;
94 case L'ч': str.append(L"ch");
95 return true;
96 case L'ш': str.append(L"sh");
97 return true;
98 case L'щ': str.append(L"sch");
99 return true;
100 case L'ы': str.append(L"y");
101 return true;
102 case L'э': str.append(L"e");
103 return true;
104 case L'ю': str.append(L"yu");
105 return true;
106 case L'я': str.append(L"ya");
107 return true;
108 case L'А': str.append(L"A");
109 return true;
110 case L'Б': str.append(L"B");
111 return true;
112 case L'В': str.append(L"V");
113 return true;
114 case L'Г': str.append(L"G");
115 return true;
116 case L'Д': str.append(L"D");
117 return true;
118 case L'Е': str.append(L"E");
119 return true;
120 case L'Ё': str.append(L"YE");
121 return true;
122 case L'Ж': str.append(L"ZH");
123 return true;
124 case L'З': str.append(L"Z");
125 return true;
126 case L'И': str.append(L"I");
127 return true;
128 case L'Й': str.append(L"Y");
129 return true;
130 case L'К': str.append(L"K");
131 return true;
132 case L'Л': str.append(L"L");
133 return true;
134 case L'М': str.append(L"M");
135 return true;
136 case L'Н': str.append(L"N");
137 return true;
138 case L'О': str.append(L"O");
139 return true;
140 case L'П': str.append(L"P");
141 return true;
142 case L'Р': str.append(L"R");
143 return true;
144 case L'С': str.append(L"S");
145 return true;
146 case L'Т': str.append(L"T");
147 return true;
148 case L'У': str.append(L"U");
149 return true;
150 case L'Ф': str.append(L"F");
151 return true;
152 case L'Х': str.append(L"H");
153 return true;
154 case L'Ц': str.append(L"Z");
155 return true;
156 case L'Ч': str.append(L"CH");
157 return true;
158 case L'Ш': str.append(L"SH");
159 return true;
160 case L'Щ': str.append(L"SCH");
161 return true;
162 case L'Ы': str.append(L"Y");
163 return true;
164 case L'ъ': str.append(L"_");
165 case L'ь': str.append(L"_");
166 case L'Ь': str.append(L"_");
167 case L'Ъ': str.append(L"_");
168 return true;
169 case L'Э': str.append(L"E");
170 return true;
171 case L'Ю': str.append(L"YU");
172 return true;
173 case L'Я': str.append(L"YA");
174 return true;
175 default:
176 str.append(std::to_wstring(static_cast<unsigned int> (c)));
177 }
178 return true;
179}
180
181
182//_Z5name1PN7newlang7ContextERNS_4ObjectE
183//_Z6name22PN7newlang7ContextERNS_4ObjectE
184//_Z7name333PN7newlang7ContextERNS_4ObjectE
185// Для типа
186//typedef ObjPtr FunctionType(Context *ctx, Object &in);
187
188std::string newlang::MangaledFuncCPP(const char *name, const char *space) {
189 std::string result("_Z");
190 result += std::to_string(strlen(name));
191 result += name;
192 result += "PN7newlang7ContextERNS_4ObjectE";
193 return result;
194}
195
196//Int8 _ZN7newlang4CharEPKNS_7ContextERKNS_6ObjectE
197//Int16 _ZN7newlang5ShortEPKNS_7ContextERKNS_6ObjectE
198//Char_ _ZN7newlang5Char_EPNS_7ContextERNS_6ObjectE
199//Short_ _ZN7newlang6Short_EPNS_7ContextERNS_6ObjectE
200
201std::string newlang::MangaledFunc(const std::string name) {
202 std::string result("_ZN7newlang");
203 result += std::to_string(name.size());
204 result += name;
205 result += isConstName(name) ? "EPNS_7ContextERNS_6ObjectE" : "EPKNS_7ContextERKNS_6ObjectE";
206 return result;
207}
208
209std::string newlang::MangleName(const char * name) {
210
211#define ALLOW_CHAR L"_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
212 static const std::wstring first_char(ALLOW_CHAR);
213 static const std::wstring next_char(L"0123456789" ALLOW_CHAR);
214#undef ALLOW_CHAR
215 std::wstring_convert < std::codecvt_utf8<wchar_t>, wchar_t> converter;
216 std::wstring temp = converter.from_bytes(name);
217
218 std::wstring result = converter.from_bytes(NEWLANG_PREFIX "_");
219 if (temp.size()) {
220 size_t len = temp.size();
221 for (size_t i = 0; i < len; i++) {
222 if (i == 0 && first_char.find(temp[i]) != std::wstring::npos) {
223 result += temp[i]; // Первый символ имени только буква или подчерк
224 } else if (i != 0 && next_char.find(temp[i]) != std::wstring::npos) {
225 result += temp[i]; // Последующие могут содержать ещё и цифры
226 } else {
227 Tranliterate(temp[i], result); // Иначе конвертировать в ASCII символы
228 }
229 }
230 }
231 return converter.to_bytes(result);
232}
233
234/*
235 *
236 *
237 */
238//std::unique_ptr<llvm::Module> JIT::MakeLLVMModule(std::string_view source, const std::vector<std::string> extra_opts, std::string *asm_code) {
239//
240// // std::unique_ptr<llvm::Module> CompileCpp(std::string source, std::vector<std::string> opts, std::string *asm_code = nullptr) {
241// clang::CompilerInstance compilerInstance;
242// auto& compilerInvocation = compilerInstance.getInvocation();
243//
244//
254//
255//
256// // Целевая платформа
257// std::string triple = LLVMGetDefaultTargetTriple();
258//
259// std::vector<std::string> run_opts;
260// run_opts.push_back(triple.insert(0, "-triple="));
261//
262// run_opts.push_back("-xc++");
263//
264// run_opts.push_back("-DBUILD_UNITTEST");
265// run_opts.push_back("-DBUILD_DEBUG ");
266// run_opts.push_back("-DLOG_LEVEL_NORMAL=LOG_LEVEL_DEBUG");
267//
268// std::string build_options_string;
269// for (size_t i = 0; i < newlang_build_options_size; i++) {
270// build_options_string += newlang_build_options_arr[i];
271// build_options_string += " ";
272// }
273// std::vector<std::string> build_opts = RunTime::SplitChar(build_options_string, " \t\r\n");
274// build_options_string.clear();
275//
276// run_opts.insert(run_opts.end(), build_opts.begin(), build_opts.end());
277// run_opts.insert(run_opts.end(), extra_opts.begin(), extra_opts.end());
278//
279// for (auto &elem : run_opts) {
280// if (elem.find("-D") == 0) {
281// elem += " ";
282// }
283// // std::cout << elem << "\n";
284// }
285//
286// std::vector<const char*> itemcstrs;
287// for (unsigned idx = 0; idx < run_opts.size(); idx++) {
288// // note: if itemstrs is modified after this, itemcstrs will be full
289// // of invalid pointers! Could make copies, but would have to clean up then...
290// itemcstrs.push_back(run_opts[idx].c_str());
291// // std::cout << itemcstrs.back() << "\n";
292// }
293//
294// // Компиляция из памяти
295// // Send code through a pipe to stdin
296// int codeInPipe[2];
297// pipe2(codeInPipe, O_NONBLOCK);
298// write(codeInPipe[1], source.begin(), source.size());
299// close(codeInPipe[1]); // We need to close the pipe to send an EOF
300// dup2(codeInPipe[0], STDIN_FILENO);
301//
302// itemcstrs.push_back("-"); // Read code from stdin
303//
304// clang::CompilerInvocation::CreateFromArgs(compilerInvocation,
305// llvm::ArrayRef<const char *>(itemcstrs.data(),
306// itemcstrs.size()), *pDiagnosticsEngine);
307//
308// auto& languageOptions = compilerInvocation.getLangOpts();
309// auto& preprocessorOptions = compilerInvocation.getPreprocessorOpts();
310// auto& targetOptions = compilerInvocation.getTargetOpts();
311//
312// auto& frontEndOptions = compilerInvocation.getFrontendOpts();
313// // frontEndOptions.ShowStats = true;
314//
315// auto& headerSearchOptions = compilerInvocation.getHeaderSearchOpts();
316// // headerSearchOptions.Verbose = true;
317//
318// auto& codeGenOptions = compilerInvocation.getCodeGenOpts();
319//
320//
321// targetOptions.Triple = LLVMGetDefaultTargetTriple();
322// compilerInstance.createDiagnostics(textDiagPrinter, false);
323//
324// // DEBUG_MSG("Using target triple: " << triple);
325//
326// LLVMContextRef ctx = LLVMContextCreate();
327// std::unique_ptr<clang::CodeGenAction> action = std::make_unique<clang::EmitLLVMOnlyAction>((llvm::LLVMContext *)ctx);
328//
329// assert(compilerInstance.ExecuteAction(*action));
330//
331// // Runtime LLVM Module
332// std::unique_ptr<llvm::Module> module = action->takeModule();
333//
334// assert(module);
335//
336//
337// if (asm_code) {
338// llvm::raw_string_ostream asm_stream(*asm_code);
339// module->print(asm_stream, 0, false);
340// }
341// //AssemblyWriter
342//
343// // Оптимизация IR
344// // llvm::PassBuilder passBuilder;
345// // llvm::LoopAnalysisManager loopAnalysisManager;
346// // llvm::FunctionAnalysisManager functionAnalysisManager;
347// // llvm::CGSCCAnalysisManager cGSCCAnalysisManager;
348// // llvm::ModuleAnalysisManager moduleAnalysisManager;
349// //
350// // passBuilder.registerModuleAnalyses(moduleAnalysisManager);
351// // passBuilder.registerCGSCCAnalyses(cGSCCAnalysisManager);
352// // passBuilder.registerFunctionAnalyses(functionAnalysisManager);
353// // passBuilder.registerLoopAnalyses(loopAnalysisManager);
354// // passBuilder.crossRegisterProxies(loopAnalysisManager, functionAnalysisManager, cGSCCAnalysisManager, moduleAnalysisManager);
355// //
356// // llvm::ModulePassManager modulePassManager = passBuilder.buildPerModuleDefaultPipeline(llvm::OptimizationLevel::O0);
357// // modulePassManager.run(*module, moduleAnalysisManager);
358//
359// return module;
360//}
361
362std::unique_ptr<llvm::Module> JIT::MakeLLVMModule(const std::string_view source, std::vector<std::string> extra_opts, std::string temp_dir) {
363
364 clang::CompilerInstance compilerInstance;
365 auto& compilerInvocation = compilerInstance.getInvocation();
366
367
368 // // Диагностика работы Clang
369 // clang::IntrusiveRefCntPtr<clang::DiagnosticOptions> DiagOpts = new clang::DiagnosticOptions;
370 // clang::TextDiagnosticPrinter *textDiagPrinter =
371 // new clang::TextDiagnosticPrinter(llvm::outs(), &*DiagOpts);
372 //
373 // clang::IntrusiveRefCntPtr<clang::DiagnosticIDs> pDiagIDs;
374 //
375 // clang::DiagnosticsEngine *pDiagnosticsEngine =
376 // new clang::DiagnosticsEngine(pDiagIDs, &*DiagOpts, textDiagPrinter);
377
378
379 // Целевая платформа
380 std::string triple = LLVMGetDefaultTargetTriple();
381
382 std::vector<std::string> run_opts;
383 run_opts.push_back(triple);
384 run_opts.back().insert(0, "-triple=");
385
386 run_opts.push_back("-xc++");
387
388 // run_opts.push_back("-DBUILD_UNITTEST");
389 // run_opts.push_back("-DBUILD_DEBUG");
390 // run_opts.push_back("-DLOG_LEVEL_NORMAL=LOG_LEVEL_DEBUG");
391 //
392
393 std::string build_options_string;
394 for (size_t i = 0; i < newlang_build_options_size; i++) {
395 build_options_string += newlang_build_options_arr[i];
396 build_options_string += " ";
397 }
398 std::vector<std::string> build_opts = RunTime::SplitChar(build_options_string, " \t\r\n");
399 build_options_string.clear();
400
401 run_opts.insert(run_opts.end(), build_opts.begin(), build_opts.end());
402 run_opts.insert(run_opts.end(), extra_opts.begin(), extra_opts.end());
403
404 for (auto &elem : run_opts) {
405 if (elem.find("-D") == 0) {
406 elem += " ";
407 }
408 // std::cout << elem << "\n";
409 }
410
411
412 // std::vector<std::string> itemstrs;
413 // itemstrs.push_back(triple.insert(0, "-triple="));
414 // itemstrs.push_back("-xc++");
415 // itemstrs.push_back("-std=c++23");
416 //
417 // itemstrs.insert(itemstrs.end(), opts.begin(), opts.end());
418
419
420 // Компиляция из памяти
421 // Send code through a pipe to stdin
422 int codeInPipe[2];
423 pipe2(codeInPipe, O_NONBLOCK);
424
425 int writen;
426 int pipe_sz_save = fcntl(codeInPipe[1], F_GETPIPE_SZ, 0);
427
428 std::string temp_file;
429 std::string obj_file;
430 int fd_temp = 0;
431 if (pipe_sz_save / 2 < source.size()) {
432
433 close(codeInPipe[1]);
434
435 temp_file = temp_dir.empty() ? m_temp_dir : temp_dir;
436 temp_file += "/module_XXXXXX";
437 fd_temp = mkstemp(temp_file.data());
438 if (fd_temp < 0) {
439 LOG_RUNTIME("Fail create temp file %s!", temp_file.c_str());
440 }
441
442 writen = write(fd_temp, source.begin(), source.size());
443 close(fd_temp);
444 if (writen != source.size()) {
445 LOG_RUNTIME("Write error to temp file %s!", temp_file.c_str());
446 }
447
448 obj_file = temp_file;
449 obj_file += ".o";
450
451 run_opts.push_back("-o");
452 run_opts.push_back(obj_file);
453 run_opts.push_back(temp_file.c_str());
454
455 } else {
456
457 // int pipe_sz = fcntl(codeInPipe[1], F_SETPIPE_SZ, 65536 * 4);
458
459 int writen = write(codeInPipe[1], source.begin(), source.size());
460
461 if (writen != source.size()) {
462 LOG_RUNTIME("Write PIPE error: only %d of required %d bytes were written!", writen, (int) source.size());
463 }
464
465 close(codeInPipe[1]); // We need to close the pipe to send an EOF
466 dup2(codeInPipe[0], STDIN_FILENO);
467
468 run_opts.push_back("-"); // Read code from stdin
469
470 }
471
472 std::vector<const char*> itemcstrs;
473 for (unsigned idx = 0; idx < run_opts.size(); idx++) {
474 // note: if itemstrs is modified after this, itemcstrs will be full
475 // of invalid pointers! Could make copies, but would have to clean up then...
476 itemcstrs.push_back(run_opts[idx].c_str());
477 // std::cout << itemcstrs.back() << "\n";
478 }
479
480
481 clang::CompilerInvocation::CreateFromArgs(compilerInvocation,
482 llvm::ArrayRef<const char *>(itemcstrs.data(),
483 itemcstrs.size()), *pDiagnosticsEngine);
484
485 auto& languageOptions = compilerInvocation.getLangOpts();
486 auto& preprocessorOptions = compilerInvocation.getPreprocessorOpts();
487 auto& targetOptions = compilerInvocation.getTargetOpts();
488
489 auto& frontEndOptions = compilerInvocation.getFrontendOpts();
490 // frontEndOptions.ShowStats = true;
491
492 auto& headerSearchOptions = compilerInvocation.getHeaderSearchOpts();
493 // headerSearchOptions.Verbose = true;
494
495 auto& codeGenOptions = compilerInvocation.getCodeGenOpts();
496
497
498 targetOptions.Triple = LLVMGetDefaultTargetTriple();
499 compilerInstance.createDiagnostics(textDiagPrinter, false);
500
501 // std::cout << "Using target triple: " << triple;
502
503 LLVMContextRef ctx = LLVMContextCreate();
504 std::unique_ptr<clang::CodeGenAction> action = std::make_unique<clang::EmitLLVMOnlyAction>((llvm::LLVMContext *)ctx);
505
506 if (!compilerInstance.ExecuteAction(*action)) {
507 LOG_RUNTIME("Compile error!");
508 }
509
510 // Runtime LLVM Module
511 std::unique_ptr<llvm::Module> module = action->takeModule();
512
513 if (!module) {
514 LOG_RUNTIME("Fail create module!");
515 }
516
517 std::filesystem::remove(temp_file);
518
519
520 // if (asm_code) {
521 // llvm::raw_string_ostream asm_stream(*asm_code);
522 // module->print(asm_stream, 0, false);
523 // }
524
525 return module;
526 //
527 // triple = LLVMGetDefaultTargetTriple();
528 // LLVMInitializeAllTargetInfos();
529 // LLVMInitializeAllTargets();
530 // LLVMInitializeAllTargetMCs();
531 // LLVMInitializeAllAsmParsers();
532 // LLVMInitializeAllAsmPrinters();
533 //
534 // std::string Error;
535 // auto Target = llvm::TargetRegistry::lookupTarget(triple, Error);
536 //
537 // if (!Target) {
538 // LOG_ERROR("\n%s\n", Error.c_str());
539 // return false;
540 // }
541 //
542 // auto CPU = "generic";
543 // auto Features = "";
544 //
545 // llvm::TargetOptions opt;
546 // auto RM = std::optional<llvm::Reloc::Model>();
547 // auto TargetMachine = Target->createTargetMachine(triple, CPU, Features, opt, RM);
548 //
549 // module->setDataLayout(TargetMachine->createDataLayout());
550 // module->setTargetTriple(triple);
551 //
552 // auto Filename = obj_file.empty() ? "output.o" : obj_file;
553 // std::error_code EC;
554 // llvm::raw_fd_ostream dest(Filename, EC, llvm::sys::fs::OF_None);
555 //
556 // llvm::legacy::PassManager pass;
557 // auto FileType = llvm::CodeGenFileType::ObjectFile;
558 //
559 // if (TargetMachine->addPassesToEmitFile(pass, dest, nullptr, FileType)) {
560 // llvm::errs() << "TargetMachine can't emit a file of this type";
561 // return false;
562 // }
563 // pass.run(*module);
564 // dest.flush();
565 //
566 // // // llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> DiagOpts2 = new clang::DiagnosticOptions;
567 // // // clang::TextDiagnosticPrinter *DiagClient = new clang::TextDiagnosticPrinter(llvm::errs(), &*DiagOpts2);
568 // // // llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> DiagID(new clang::DiagnosticIDs());
569 // // // clang::DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagClient);
570 // // clang::driver::Driver TheDriver("", triple, *pDiagnosticsEngine);
571 // //
572 // // auto args = llvm::ArrayRef<const char *>{"-g", Filename.c_str(), "-o", execname.begin()};
573 // //
574 // // std::unique_ptr<clang::driver::Compilation> C(TheDriver.BuildCompilation(args));
575 // //
576 // // if (C && !C->containsError()) {
577 // // llvm::SmallVector<std::pair<int, const clang::driver::Command *>, 4> FailingCommands;
578 // // TheDriver.ExecuteCompilation(*C, FailingCommands);
579 // // }
580 //
581 // return true;
582}
583
584bool JIT::MakeObjFile(const std::string_view filename, llvm::Module &module, const std::vector<std::string> opts) {
585
587
588 std::string triple = LLVMGetDefaultTargetTriple();
589
590 std::string Error;
591 auto Target = llvm::TargetRegistry::lookupTarget(triple, Error);
592
593 if (!Target) {
594 LOG_ERROR("\n%s\n", Error.c_str());
595 return false;
596 }
597
598 auto CPU = "generic";
599 auto Features = "";
600
601 llvm::TargetOptions opt;
602 auto RM = std::optional<llvm::Reloc::Model>();
603 auto TargetMachine = Target->createTargetMachine(triple, CPU, Features, opt, RM);
604
605 module.setDataLayout(TargetMachine->createDataLayout());
606 module.setTargetTriple(triple);
607
608 // auto Filename = obj_file.empty() ? "output.o" : obj_file;
609 std::error_code EC;
610 llvm::raw_fd_ostream dest(filename.begin(), EC, llvm::sys::fs::OF_None);
611
612 llvm::legacy::PassManager pass;
613 auto FileType = llvm::CodeGenFileType::ObjectFile;
614
615 if (TargetMachine->addPassesToEmitFile(pass, dest, nullptr, FileType)) {
616 llvm::errs() << "TargetMachine can't emit a file of this type";
617 return false;
618 }
619 pass.run(module);
620 dest.flush();
621 return true;
622}
623
624bool JIT::LinkObjToExec(const std::string_view execname, std::vector<std::string> objs, std::vector<std::string> opts) {
625
626 clang::driver::Driver TheDriver("", LLVMGetDefaultTargetTriple(), *pDiagnosticsEngine);
627
628
629 objs.insert(objs.begin(), opts.begin(), opts.end());
630
631 objs.insert(objs.begin(), "-g");
632 objs.push_back("-o");
633 objs.push_back(execname.begin());
634
635
636
637 std::vector<const char*> args;
638 for (unsigned idx = 0; idx < objs.size(); idx++) {
639 // note: if itemstrs is modified after this, itemcstrs will be full
640 // of invalid pointers! Could make copies, but would have to clean up then...
641 args.push_back(objs[idx].c_str());
642 // std::cout << args.back() << "\n";
643 }
644
645 // auto args = llvm::ArrayRef<const char *>{"-g", Filename.c_str(), "-o", execname.begin()};
646 // auto args = llvm::ArrayRef<const char *>(objs.begin(), objs.end());
647
648 std::unique_ptr<clang::driver::Compilation> C(TheDriver.BuildCompilation(args));
649
650 if (C && !C->containsError()) {
651 llvm::SmallVector<std::pair<int, const clang::driver::Command *>, 4> FailingCommands;
652 TheDriver.ExecuteCompilation(*C, FailingCommands);
653 }
654
655 return true;
656}
657
658/*
659 *
660 *
661 *
662 */
663
664
665std::string JIT::ExtractFunctionDecls(const TermPtr &term, const std::string_view module) {
666 std::string result;
667 if (term->isBlock()) {
668 for (auto &elem : term->m_block) {
669 result += ExtractFunctionDecls(elem, module);
670 }
671 } else {
672 if (term->isCreate() && term->m_left->isCall()) {
673 result += "// ";
674 result += MakeCommentPlace(term->m_left);
675 result += "\n";
676 result += "extern \"C\" ";
677 result += MakeFunctionPrototype(term->m_left, module);
678 result += ";\n";
679 }
680 }
681 return result;
682}
683
684std::string JIT::MakeFunctionPrototype(const TermPtr &func, const std::string_view module) {
685 ASSERT(func->isCall());
686 if (func->m_normalized.empty()) {
687 NL_PARSER(func, "Has no internal name! AST analysis required!");
688 }
689 std::string result(NEWLANG_NS "::ObjPtr ");
690 result += func->m_normalized.getMangledName(module);
691 result += "(" NEWLANG_NS "::Context *ctx, " NEWLANG_NS "::Obj &args)";
692 return result;
693}
694
695std::string JIT::MakeCommentPlace(const TermPtr &term) {
696 std::string comment = term->toString();
697 if (term->m_line) {
698 comment += " at line: ";
699 comment += std::to_string(term->m_line);
700 }
701 return RegExpInlineComment(comment);
702}
703
704std::string JIT::RegExpInlineComment(const std::string_view src) {
705 std::string comment(src);
706 comment = std::regex_replace(comment, std::regex("\n"), "\\n");
707 comment = std::regex_replace(comment, std::regex("\""), "@\"");
708 return comment;
709}
710
713 result->push_back(Term::CreateName("argc"));
714 result->back().second->m_type = Term::CreateName(":Int32", TermID::TYPE);
715 result->push_back(Term::CreateName("argv"));
716 result->back().second->m_type = Term::CreateName(":StrChar", TermID::TYPE);
717 result->push_back(Term::CreateName("penv"));
718 result->back().second->m_type = Term::CreateName(":StrChar", TermID::TYPE);
719 return result;
720}
721
722std::string JIT::MakeApplicationSource(const TermPtr &ast) {
723 std::string result;
724 if (!ast->isBlock() && ast->m_id == TermID::EMBED) {
725 std::string source = ReplaceObjectInEmbedSource(ast->m_text, m_includes, MainArgs());
726 if (source.compare(ast->m_text) == 0) {
727 // Simple embedded (no libnlc-rt)
729 } else {
730 // Need link libnlc-rt
731 if (!m_link_rt) {
732 LOG_RUNTIME("Options '--nlc-no-link-rt' not allowed!");
733 }
735 }
736 } else {
737 if (!m_link_rt) {
738 LOG_RUNTIME("Options '--nlc-no-link-rt' not allowed!");
739 }
740 // if (!m_rt->m_link_rt || !m_rt->m_link_jit) {
741 // LOG_RUNTIME("Options '--nlc-no-link-rt' or '--nlc-no-link-jit' not allowed!");
742 // }
743 // Need link libnlc-rt and libnlc-jit
744 LOG_RUNTIME("Not implemented!!!");
745 }
746 return result;
747}
748
749std::string JIT::MakeMain(const std::vector<std::string> &include) {
750 std::string result;
751 result += NEWLANG_INDENT_OP NEWLANG_INDENT_OP "return newlang::RunMain(argc, argv, penv);";
752 return MakeMainEmbed(result, include);
753}
754
755std::string JIT::MakeMainEmbed(const std::string_view embed_source, const std::vector<std::string> &include) {
756 std::string result;
757 result += "/*\n* Generate NewLang JIT::MakeMainEmbed";
759 result += "\n* at: ";
761 result += "\n*/\n\n";
762
763 std::string filename;
764 for (auto &elem : include) {
765 result += "#include ";
766 if (elem.find("\\") == 0) {
767 result += "<>\n";
768 filename = elem.substr(1);
769 } else {
770 result += "\"\"\n";
771 filename = elem;
772 }
773 // filename = std::regex_replace(filename, std::regex("\\\\\\\\"), "\\");
774 std::replace(filename.begin(), filename.end(), '\\', '/');
775 result = result.insert(result.size() - 2, filename);
776 }
777 result += "\n\nnamespace newlang {\n";
778 result += NEWLANG_INDENT_OP "int RunMain(const int argc, const char** argv, const char** penv);\n";
779 result += "}\n\n";
780 result += "int main(const int argc, const char* argv[], const char* penv[]) {\n\n";
781 result += NEWLANG_INDENT_OP NEWLANG_INDENT_OP "// disable unused warning\n";
782 result += NEWLANG_INDENT_OP NEWLANG_INDENT_OP "((void)(argc)); ((void)(argv)); ((void)(penv));\n\n";
783 result += embed_source;
785 return result;
786}
787
788/*
789 * @\\stdio.h --> #include <stdio.h>
790 * @\sys\time.h --> #include "sys/time.h"
791 */
792std::string JIT::ReplaceObjectInEmbedSource(const std::string_view embed, std::vector<std::string> &include, const TermPtr args) {
793 std::string result(embed);
794
795 size_t pos = result.find("@\\");
796 while (pos != std::string::npos) {
797 include.push_back(result.substr(pos + 2, result.find_first_of(" \t\n\r*/$#\"'[]%;:", pos + 2) - pos - 2));
798 pos = result.find("@\\", pos + 2);
799 }
800
801 if (args) {
802 std::string arg_name;
803 std::string arg_place;
804 for (size_t i = 0; i < args->size(); i++) {
805 // Заменить номер аргумента
806 arg_name = "@$" + std::to_string(i);
807 arg_place = "in[" + std::to_string(i) + "]";
808 result = std::regex_replace(result, std::regex(arg_name), arg_place);
809 }
810
811 for (auto &elem : *args) {
812 // Заменить имя аргумента
813 arg_name = MakeName(elem.first);
814 arg_place = "in[\"" + arg_name + "\"]";
815 arg_name = "@$" + arg_name;
816 result = std::regex_replace(result, std::regex(arg_name), arg_place);
817 }
818 }
819 return result;
820}
821
822std::string JIT::MakeCodeModule(const TermPtr &ast, const std::string_view module, bool is_main) {
823 std::string result;
824 for (size_t i = 0; i < newlang_include_h_i_size; i++) {
825 result += newlang_include_h_i_arr[i];
826 result += "\n";
827 }
828
829 result += "/*\n* Generate NewLang JIT::MakeCodeModule";
831 result += "\n* at: ";
833 result += "\n*/\n\n";
834
835 // result += "#include <memory>\n";
836 // result += "\n";
837 //
838 // result += "namespace newlang {\n";
839 // result += " class Obj;\n";
840 // result += " class Context;\n";
841 // result += " typedef std::shared_ptr<Obj> ObjPtr;\n";
842 // result += "};\n\n";
843
844 result += ExtractFunctionDecls(ast, module);
845
846 result += ExtractStaticVars(ast, module);
847
848 TermPtr func_module = Term::CreateName("__module__");
849 func_module->m_is_call = true;
850 func_module->m_normalized = NormalizeName(func_module->m_text);
851
852 result += MakeFunctionPrototype(func_module, module);
853 result += " {\n";
854 result += MakeBodyFunction(ast);
855 result += " return nullptr;\n";
856 result += "}\n";
857
858 MakeFunctionRecursive_(ast, result, module);
859
860 result += "/*\n* End generate JIT::MakeCodeModule";
862 result += "\n* at: ";
864 result += "\n*/\n\n";
865 return result;
866}
867
868std::string JIT::MakeCodeRepl(const std::string_view source, const std::string_view func_name) {
869
870 // TermPtr ast = MakeAst(source);
871 //
872 std::string result;
873 // for (size_t i = 0; i < newlang_include_h_i_size; i++) {
874 // result += newlang_include_h_i_arr[i];
875 // result += "\n";
876 // }
877 //
878 // result += "/*\n* Generate NewLang JIT::MakeCodeRepl";
879 // result += "\n* " VERSION_SOURCE_FULL_ID;
880 // result += "\n* at: ";
881 // result += Parser::GetCurrentTimeStamp();
882 // result += "\n* from source:\n* ";
883 // result += RegExpInlineComment(source);
884 // result += "\n*/\n\n";
885 //
886 // result += "using namespace newlang;\n\n";
887
888 // // result += ExtractFunctionDecls(ast, module);
889 // // result += ExtractStaticVars(ast, module);
890 //
891 // TermPtr func_module = Term::CreateName(func_name);
892 // func_module->m_is_call = true;
893 // func_module->m_normalized = NormalizeName(func_module->m_text);
894 //
895 // result += MakeFunctionPrototype(func_module, module);
896 // result += " {\n";
897 // result += MakeBodyFunction(ast);
898 // result += " return JitLastResult(nullptr);\n";
899 // result += "}\n";
900 //
901 // MakeFunctionRecursive_(ast, result, module);
902 //
903 // result += "/*\n* End generate NewLang JIT::MakeCodeRepl";
904 // result += "\n* " VERSION_SOURCE_FULL_ID;
905 // result += "\n* at: ";
906 // result += Parser::GetCurrentTimeStamp();
907 // result += "\n* from source:\n* ";
908 // result += RegExpInlineComment(source);
909 // result += "\n*/\n\n";
910 return result;
911}
912
913std::string JIT::ExtractStaticVars(const TermPtr &ast, const std::string_view module) {
914 return "";
915}
916
917std::string JIT::MakeCodeFunction(const TermPtr &term) {
918 return "";
919}
920
921std::string JIT::MakeFuncDeclarations_(const TermPtr &term) {
922 return "";
923}
924
925std::string JIT::MakeBodyFunction(const TermPtr &ast) {
926 return "";
927}
928
929void JIT::MakeFunctionRecursive_(const TermPtr &term, std::string &output, const std::string_view module) {
930 // std::string result;
931 if (term->isBlock()) {
932 for (auto &elem : term->m_block) {
933 MakeFunctionRecursive_(elem, output, module);
934 }
935 } else {
936 if (term->isCreate()) {
937 if (term->m_left->isCall()) { // Function
938 output += "// ";
939 output += MakeCommentPlace(term);
940 output += "\n\n";
941 output += "extern \"C\" ";
942 output += MakeFunctionPrototype(term->m_left, module);
943 output += " {\n";
944 output += MakeBodyFunction(term->m_right);
945 output += "}\n";
946 }
947 }
948 }
949 // return result;
950}
951
952std::string CompileInfo::GetIndent(int64_t offset) {
953 return repeat(std::string(NEWLANG_INDENT_OP), indent + offset);
954}
955
956
957
958//TermPtr CompileInfo::isFunction(TermPtr term) {
959// ASSERT(term);
960// if (term) {
961// std::string local_name = term->GetFullName();
962// if (functions.find(local_name) != functions.end()) {
963// return functions.find(local_name)->second;
964// }
965// if (builtin.find(local_name) != builtin.end()) {
966// return builtin.find(local_name)->second;
967// }
968// }
969// return nullptr;
970//}
971//
972//TermPtr CompileInfo::isArgument(TermPtr term) {
973// ASSERT(term);
974// if (term) {
975// std::string local_name = MakeName(term->GetFullName().c_str());
976// if (arguments.find(local_name) != arguments.end()) {
977// return arguments.find(local_name)->second;
978// }
979// }
980// return nullptr;
981//}
982//
983//TermPtr CompileInfo::isVariable(TermPtr term) {
984// ASSERT(term);
985// if (term) {
986// std::string local_name = MakeName(term->GetFullName().c_str());
987// if (variables.find(local_name) != variables.end()) {
988// return variables.find(local_name)->second;
989// }
990// }
991// return nullptr;
992//}
993//
994//TermPtr CompileInfo::findObject(std::string name) {
995// name = MakeName(name);
996// if (arguments.find(name) != arguments.end()) {
997// return arguments.find(name)->second;
998// }
999// if (variables.find(name) != variables.end()) {
1000// return variables.find(name)->second;
1001// }
1002// if (consts.find(name) != consts.end()) {
1003// return consts.find(name)->second;
1004// }
1005// if (functions.find(name) != functions.end()) {
1006// return functions.find(name)->second;
1007// }
1008// if (builtin.find(name) != builtin.end()) {
1009// return builtin.find(name)->second;
1010// }
1011// return nullptr;
1012//}
1013//
1014//bool CompileInfo::isLocalAccess(TermPtr term) {
1015// ASSERT(term);
1016// std::string name = MakeName(term->GetFullName());
1017// return variables.find(name) != variables.end() || consts.find(name) != consts.end();
1018//}
1019//
1020//void Compiler::WriteDeclarationFunctions_(CompileInfo &ci, TermPtr &func, std::ostream & out, std::vector<std::string> &func_list) {
1021// if (func->IsFunction()) {
1022// ASSERT(func->Left());
1023// ci.functions.insert(std::pair<std::string, TermPtr>(func->Left()->GetFullName().c_str(), func->Left()));
1024// WriteFunctionName_(func, out);
1025// out << ";\n";
1026// out << "extern \"C\" const ObjPtr " << MangleName(func->Left()->GetFullName().c_str()) << "_arguments;\n";
1027// out << "inline " NEWLANG_NS "::ObjPtr " << MangleName(func->Left()->GetFullName().c_str()) << "(" NEWLANG_NS "::Context *ctx, " NEWLANG_NS "::ObjPtr args) {\n";
1028// out << "ObjPtr temp=" << MangleName(func->Left()->GetFullName().c_str()) << "_arguments->Call" << "(*args);\n";
1029// // out << NEWLANG_INDENT_OP "args->UpdateFrom( *" << MangleName(func->Left()->GetFullName().c_str()) << "_arguments" << ");\n";
1030//
1031// out << NEWLANG_INDENT_OP "return " << MangleName(func->Left()->GetFullName().c_str()) << "(ctx, *temp);\n";
1032// out << "}\n";
1033// out << "extern \"C\" const char * " << MangleName(func->Left()->GetFullName().c_str()) << "_text;\n";
1034// func_list.push_back(func->Left()->GetFullName());
1035// } else if (func->getTermID() == TermID::BLOCK) {
1036// for (TermPtr &elem : func->BlockCode()) {
1037// WriteDeclarationFunctions_(ci, elem, out, func_list);
1038// }
1039// }
1040//}
1041//
1042//std::string Compiler::WriteFunctionCheckOp_(CompileInfo &ci, TermPtr &op, const char *check_true, const char *check_false) {
1043// std::string str;
1044//
1045// std::string result;
1046//
1047// auto indent = ci.NewIndent();
1048//
1049// result = ci.GetIndent() + "if(static_cast<bool>(";
1050// TermID id = op->getTermID();
1051// if (id == TermID::NAME || op->isCall()) {
1052//
1053// GetImpl(ci, op, result);
1054// result += "->GetValueAsBoolean()";
1055//
1056// } else if (id == TermID::OPERATOR || id == TermID::CREATE_NEW) {
1057//
1058// result += "(*";
1059//
1060// GetImpl(ci, op->Left(), result);
1061//
1062// if (op->getText().compare(":=") == 0) {
1063// result += "=";
1064// } else {
1065// result += op->getText();
1066// result += " *";
1067// }
1068//
1069// GetImpl(ci, op->Right(), result);
1070// result += ")->GetValueAsBoolean()";
1071//
1072// } else {
1073// LOG_RUNTIME("Check operation '%s' as type %s not implemented!", op->toString().c_str(), newlang::toString(id));
1074// }
1075// result += ")) {\n " + ci.GetIndent();
1076// result += check_true;
1077// result += ";\n } else {\n " + ci.GetIndent();
1078// result += check_false;
1079// result += ";\n" + ci.GetIndent() + "}\n";
1080//
1081// return result;
1082//}
1083//
1084//void Compiler::SelectTerms_(TermPtr &obj, std::vector<TermPtr> &terms) {
1085// if (obj->getTermID() == TermID::NAME) {
1086// terms.push_back(obj);
1087// }
1088// if (obj->Left()) {
1089// SelectTerms_(obj->m_left, terms);
1090// }
1091// if (obj->Right()) {
1092//
1093// SelectTerms_(obj->m_right, terms);
1094// }
1095//}
1096//
1097//bool Compiler::WriteFunctionName_(TermPtr &func, std::ostream & out, bool is_transparent) {
1098// out << "extern \"C\" " NEWLANG_NS "::ObjPtr " << MangleName(func->Left()->GetFullName().c_str()) << "(" NEWLANG_NS "::Context " << (is_transparent ? "const" : "") << " *ctx, " NEWLANG_NS "::Object &in)";
1099//
1100// return true;
1101//}
1102//
1103//std::string Compiler::MakeCommentLine(std::string comment) {
1104// comment = std::regex_replace(comment, std::regex("\n"), "\\n");
1105// comment = std::regex_replace(comment, std::regex("\""), "@\"");
1106//
1107// return "// " + comment + "\n";
1108//}
1109//
1110//std::string Compiler::WriteSimpleBody_(CompileInfo &ci, TermPtr &func) {
1111// ASSERT(!"Not implemented");
1112// // auto indent = ci.NewIndent();
1113// // WriteFunctionOp *func_op;
1114// // if(func->getTermID() != TermID::SIMPLE) {
1115// // LOG_RUNTIME("Term is not a simple pure function %s(%d) %s", newlang::toString(func->getTermID()), (int) func->getTermID(), func->toString().c_str());
1116// // }
1117// //
1118// // if(func->getText().compare(":&&=") == 0) {
1119// // func_op = &WriteSimpleBodyAND_;
1120// // } else if(func->getText().compare(":||=") == 0) {
1121// // func_op = &WriteSimpleBodyOR_;
1122// // } else if(func->getText().compare(":^^=") == 0) {
1123// // func_op = &WriteSimpleBodyXOR_;
1124// // } else {
1125// // LOG_RUNTIME("Unknown function type %s(%d) %s", newlang::toString(func->getTermID()), (int) func->getTermID(), func->toString().c_str());
1126// // }
1127// //
1128// // std::string temp;
1129// // std::string result = (*func_op)(ci, func, FunctionStep::PREPARE);
1130// //
1131// // if(func->Right()->getTermID() == TermID::BLOCK) {
1132// // for (auto &elem : func->Right()->BlockCode()) {
1133// //
1134// // // В комментарий добавляется исходный код, в котором могут быть текстовые строки с управляющими символами
1135// // result += "\n" + ci.GetIndent() + MakeCommentLine(elem->toString());
1136// //
1137// // temp = (*func_op)(ci, elem, FunctionStep::OPERATION);
1138// // // ReplaceFuncArgs(func, temp);
1139// // result += temp;
1140// //
1141// // }
1142// // } else {
1143// //
1144// // TermPtr term = func->Right();
1145// //
1146// // // В комментарий добавляется исходный код, в котором могут быть текстовые строки с управляющими символами
1147// // result += "\n" + ci.GetIndent() + MakeCommentLine(term->toString());
1148// //
1149// // temp = (*func_op)(ci, term, FunctionStep::OPERATION);
1150// //
1151// // // ReplaceFuncArgs(func, temp);
1152// // result += temp;
1153// // }
1154// //
1155// // result += (*func_op)(ci, func, FunctionStep::COMPLETE);
1156// //
1157// // return result;
1158// return "";
1159//}
1160
1161
1162
1163//bool Compiler::MakeFunctionCpp(CompileInfo &ci, std::string func_name, TermPtr &func_define, std::ostream &out) {
1164// LOG_RUNTIME("MakeFunctionCpp Not implemeneted!");
1165// // if(!func_define->IsFunction()) {
1166// // LOG_RUNTIME("No function name");
1167// // }
1168// // if(!func_define->Right()) {
1169// // LOG_RUNTIME("No function body");
1170// // }
1171// //
1172// // std::string text = func_define->toString();
1173// // text = std::regex_replace(text, std::regex("\""), "@\"");
1174// // text = std::regex_replace(text, std::regex("\n"), "\\n");
1175// // text = std::regex_replace(text, std::regex("\t"), "@t");
1176// // text = std::regex_replace(text, std::regex("\r"), "@r");
1177// // text = std::regex_replace(text, std::regex("\b"), "@b");
1178// // text = std::regex_replace(text, std::regex("\f"), "@f");
1179// // out << "const char * " << MangleName(func_define->Left()->GetFullName().c_str()) << "_text";
1180// // out << "=\"" << text << "\";\n";
1181// //
1182// // out << "const ObjPtr " << MangleName(func_define->Left()->GetFullName().c_str()) << "_arguments";
1183// // out << "=Obj::CreateDict(Obj::ArgNull(\"self\")";
1184// // if(func_define->Left()->size()) {
1185// // for (size_t i = 0; i < func_define->Left()->size(); i++) {
1186// // out << ", ";
1187// // std::string var_name;
1188// // if(func_define->Left()->name(i).empty()) {
1189// // var_name = func_define->Left()->at(i).second->GetFullName();
1190// // out << "Obj::ArgNull(";
1191// //
1192// // } else {
1193// // out << "Obj::Arg(";
1194// // var_name = func_define->Left()->name(i);
1195// // std::string impl;
1196// // GetImpl(ci, func_define->Left()->at(i).second, impl);
1197// // out << impl;
1198// // out << ", ";
1199// // }
1200// // out << "\"" << var_name << "\")";
1201// // }
1202// // }
1203// // out << ");";
1204// // out << " // Default function args \n";
1205// //
1206// //
1207// // WriteFunctionName_(func_define, out);
1208// // out << " {\n";
1209// //
1210// //
1211// // // Аргументы функции с локальным доступом по имени или индексу
1212// // if(func_define->Left()->size()) {
1213// // for (size_t i = 0; i < func_define->Left()->size(); i++) {
1214// // std::string var_name;
1215// // if(func_define->Left()->name(i).empty()) {
1216// // var_name = func_define->Left()->at(i).second->GetFullName();
1217// // } else {
1218// // var_name = func_define->Left()->name(i);
1219// // }
1220// // ci.arguments.insert(std::pair<std::string, TermPtr>(var_name, func_define->Left()));
1221// // }
1222// // }
1223// //
1224// // std::string body;
1225// // if(func_define->getTermID() == TermID::SIMPLE) {
1226// // body = WriteSimpleBody_(ci, func_define);
1227// // } else {
1228// // body = MakeFunctionBodyCpp(ci, func_define->Right());
1229// // }
1230// //
1231// // out << body;
1232// //
1233// // // Проверка типа возвращаемого значения из функции
1234// // NL_TYPECHECK(func_define->Left(), func_define->Left()->m_type_name, ci.last_type);
1235// //
1236// // out << "}\n";
1237// //
1238// // ci.arguments.clear();
1239// //
1240// // return true;
1241//
1242//}
1243//
1244//void Compiler::MakeCppFileFunctions(CompileInfo &ci, TermPtr ast, std::ostream &out) {
1245// if (ast->getTermID() == TermID::BLOCK) {
1246// for (TermPtr &elem : ast->BlockCode()) {
1247// MakeCppFileFunctions(ci, elem, out);
1248// }
1249// } else if (ast->IsFunction()) {
1250// // out << "#line " << ast->GetLine() << "\n";
1251// MakeFunctionCpp(ci, ast->Left()->getText(), ast, out);
1252// }
1253//}
1254//
1255//void Compiler::MakeCppFileConstants(CompileInfo &ci, TermPtr ast, std::ostream &out) {
1256// // if(ast->getTermID() == TermID::BLOCK) {
1257// // for (TermPtr &elem : ast->BlockCode()) {
1258// // MakeCppFileConstants(ci, elem, out);
1259// // }
1260// // } else if(ast->getTermID() == TermID::CREATE_NEW && isConst(ast->Left()->m_text.c_str())) {
1261// // ASSERT(ast->Left());
1262// // ASSERT(ast->Right());
1263// //
1264// // // out << "#line " << ast->GetLine() << "\n";
1265// // std::string impl_name = MakeLocalName(ast->Left()->GetFullName().c_str());
1266// // ci.consts.insert(std::pair<std::string, TermPtr>(MakeName(ast->Left()->GetFullName()), ast->Left()));
1267// // NL_TYPECHECK(ast->Left(), ast->Right()->m_type_name, ast->Left()->m_type_name);
1268// //
1269// // out << ci.GetIndent() << "static const ObjPtr " << impl_name;
1270// // std::string impl;
1271// // GetImpl(ci, ast->Right(), impl);
1272// // out << "=" << impl << "->MakeConst(); ";
1273// // out << "// " << ast->toString() << "\n";
1274// // }
1275//}
1276//
1277//std::string Compiler::MakeFunctionBodyCpp(CompileInfo &ci, TermPtr ast) {
1278// std::string result;
1279// if (ast->getTermID() == TermID::BLOCK) {
1280// for (size_t i = 0; i < ast->BlockCode().size(); i++) {
1281// if (i < ast->BlockCode().size() - 1) {
1282// result += MakeSequenceOpsCpp(ci, ast->BlockCode()[i], false);
1283// } else {
1284// result += MakeSequenceOpsCpp(ci, ast->BlockCode()[i], true);
1285// }
1286// }
1287// } else {
1288// result = MakeSequenceOpsCpp(ci, ast, true);
1289// }
1290// return result;
1291//}
1292//
1293//std::string Compiler::MakeSequenceOpsCpp(CompileInfo &ci, TermPtr ast, bool top_level) {
1294//
1295// // auto indent = ci.NewIndent();
1296// // std::ostringstream ostr;
1297// std::string result;
1298// // std::string temp;
1299// //
1300// // std::string last_item;
1301// // TermPtr last_term = ast;
1302// // if(ast->getTermID() == TermID::BLOCK) {
1303// //
1304// // for (size_t i = 0; i < ast->BlockCode().size(); i++) {
1305// // TermPtr elem = ast->BlockCode()[i];
1306// // if(top_level && i == ast->BlockCode().size() - 1) {
1307// // last_item = MakeSequenceOpsCpp(ci, elem, false);
1308// // result += last_item;
1309// // last_term = elem;
1310// // } else {
1311// // result += MakeSequenceOpsCpp(ci, elem, false);
1312// // }
1313// // }
1314// // } else if(!(ast->IsFunction() || (ast->getTermID() == TermID::CREATE_NEW && isConst(ast->Left()->m_text.c_str())))) {
1315// //
1316// // // out << "#line " << ast->GetLine() << "\n";
1317// // result += ci.GetIndent() + MakeCommentLine(ast->toString());
1318// // last_item = GetImpl(ci, ast, temp);
1319// // // result += ci.GetIndent() + temp;
1320// // // result += ";\n";
1321// // // result += ci.GetIndent();
1322// // // last_item = GetImpl(ci, ast, result);
1323// // // result += "; " + MakeCommentLine(ast->toString());
1324// // }
1325// //
1326// // if(top_level) {
1327// // if(!last_item.empty()) {
1328// // // NL_TYPECHECK(last_term, ci.last_type, ast->m_type);
1329// // // if(!canCast(ci.last_type, last_term->m_type)) {
1330// // // Parser::RaiseException("Incompatible data type '%s' to '%s'", *ast->m_source, last_term->m_line, last_term->m_col);
1331// // // }
1332// //
1333// // // NL_CHECK(canCast(ci.last_type, ast->m_type), "Incompatible data type '%s' to '%s'",
1334// // // ci.last_type.empty() ? newlang::toString(ObjType::None) : ci.last_type.c_str(),
1335// // // ast->m_type.c_str());
1336// // result += ci.GetIndent() + "return " + last_item + ";\n";
1337// // } else {
1338// // // NL_TYPECHECK(last_term, "", ast->m_type);
1339// // // NL_CHECK(canCast("", ast->m_type), "Incompatible data type '%s' to '%s'", newlang::toString(ObjType::None), ast->m_type.c_str());
1340// // result += ci.GetIndent() + "return Obj::CreateNone(); // default return\n";
1341// // }
1342// // } else {
1343// // result += ci.GetIndent() + temp;
1344// // result += ";\n";
1345// // }
1346// return result;
1347//}
1348//
1349//std::string Compiler::MakeCppFileVariable(CompileInfo &ci, TermPtr &var, std::ostream &out) {
1350// ASSERT(var->Left());
1351// ASSERT(var->Right());
1352// std::string local_name = MakeName(var->Left()->GetFullName());
1353// std::string impl_name = MakeLocalName(local_name);
1354//
1355// bool is_new = false;
1356// out << ci.GetIndent(-1);
1357// if (ci.isArgument(var->Left())) {
1358// // Аргумент
1359// impl_name = local_name;
1360// } else if (!ci.isVariable(var->Left())) {
1361// if (var->Left()->Right()) {
1362// NL_PARSER(var->Left()->Right(), "First you need to create a variable! %s", var->toString().c_str());
1363// }
1364// // Создать новую локальную переменную
1365// is_new = true;
1366// ci.variables.insert(std::pair<std::string, TermPtr>(local_name, var->Left()));
1367// out << "ObjPtr " << impl_name;
1368// } else {
1369// std::string impl;
1370// GetImpl(ci, var->Left(), impl);
1371// out << impl;
1372// }
1373//
1374// std::string temp2;
1375// GetImpl(ci, var->Right(), temp2);
1376// out << "=" << temp2 << "; ";
1377//
1378// TermPtr term = ci.findObject(var->Right()->GetFullName());
1379// if (term) {
1380// NL_TYPECHECK(var->Left(), term->m_type_name, var->Left()->m_type_name);
1381// }
1382//
1383// if (is_new) {
1384// if (var->getTermID() == TermID::CREATE_NEW) {
1385// out << "ctx->CreateGlobalTerm(" << impl_name << ", \"" << local_name << "\"); ";
1386// } else {
1387// if (var->Left()->getTermID() != TermID::ARGUMENT) {
1388// out << "ctx->CreateSessionTerm(" << impl_name << ", \"" << local_name << "\"); ";
1389// }
1390// }
1391// }
1392// out << "\n";
1393// return impl_name;
1394//}
1395//
1396//std::string Compiler::MakeCppFileCallArgs(CompileInfo &ci, TermPtr &args, TermPtr proto) {
1397// std::string result;
1398// for (int i = 0; i < args->size(); i++) {
1399// if (i) {
1400// result += ", ";
1401// }
1402// std::string impl;
1403// GetImpl(ci, args->at(i).second, impl);
1404//
1405// if (proto) {
1406// if (i < proto->size()) {
1407// TermPtr term = (*proto)[i].second;
1408// if (args->at(i).second) {
1409// NL_TYPECHECK(args->at(i).second, args->at(i).second->m_type_name, term->m_type_name);
1410// }
1411// } else if (!proto->is_variable_args()) {
1412// NL_PARSER(args->at(i).second, "Extra argument error");
1413// }
1414// }
1415//
1416// if (args->at(i).first.empty()) {
1417// result += "Obj::Arg(" + impl + ")";
1418// } else {
1419// result += "Obj::Arg(" + impl + ", \"" + args->at(i).first + "\")";
1420// }
1421// // }
1422// }
1423// return result;
1424//}
1425//
1426//std::string Compiler::EncodeNonAsciiCharacters(const char * in) {
1427// std::string text(in);
1428// text = std::regex_replace(text, std::regex("\""), "@\"");
1429// text = std::regex_replace(text, std::regex("\n"), "@x0A\" \"");
1430// text = std::regex_replace(text, std::regex("@\\n"), "@\\n");
1431//
1432// std::string src;
1433// for (size_t i = 0; i < text.length(); i++) {
1434// if (static_cast<unsigned char> (text[i]) > 127) {
1435// src += "@x";
1436// src += BinToHex((const uint8_t *) &text[i], 1);
1437// } else {
1438//
1439// src += text[i];
1440// }
1441// }
1442// return src;
1443//}
1444//
1445//bool Compiler::MakeCppFile(TermPtr ast, std::ostream &out, const char * source, Context *ctx) {
1446//
1447// CompileInfo ci(RunTime::Init());
1448//
1449// // RunTime::Instance()->ReadBuiltIn(ci);
1450//
1451//
1452// WriteIncludeFiles_(out);
1453//
1454// if (source) {
1455// std::string src(source);
1456// out << "\n//Module source\n";
1457// out << "extern \"C\" const char * " NEWLANG_PREFIX "_module_source;\n";
1458// out << "const char * " NEWLANG_PREFIX "_module_source=\"" << EncodeNonAsciiCharacters(src.c_str()) << "\";\n\n";
1459// }
1460//
1461// out << "//Module function declarations\n";
1462// out << "extern \"C\" " NEWLANG_NS "::ObjPtr " NEWLANG_PREFIX "_main_module_func(" NEWLANG_NS "::Context *ctx, " NEWLANG_NS "::Object &in);\n";
1463//
1464// std::vector<std::string> func_list;
1465// WriteDeclarationFunctions_(ci, ast, out, func_list);
1466//
1467// out << "\n//List of module funtions\n";
1468// out << "extern \"C\" const size_t " NEWLANG_PREFIX "_func_list_count=" << func_list.size() << ";\n";
1469// out << "extern \"C\" const char * " NEWLANG_PREFIX "_func_list[" << func_list.size() << "];\n";
1470// out << "const char * " NEWLANG_PREFIX "_func_list[" << func_list.size() << "] = {\n";
1471// for (auto elem : func_list) {
1472// out << NEWLANG_INDENT_OP "\"" << elem.c_str() << "\",\n";
1473// }
1474// out << "};\n";
1475//
1476//
1477// out << "\n//Constants form module\n";
1478// MakeCppFileConstants(ci, ast, out);
1479//
1480// out << "\n//Main function module\n";
1481// out << "extern \"C\" " NEWLANG_NS "::ObjPtr " NEWLANG_PREFIX "_main_module_func(" NEWLANG_NS "::Context *ctx, " NEWLANG_NS "::Object &in) {\n";
1482//
1483// out << MakeFunctionBodyCpp(ci, ast);
1484// out << "}\n";
1485//
1486// out << "\n//Module function code\n";
1487// MakeCppFileFunctions(ci, ast, out);
1488//
1489// return true;
1490//}
1491//
1492//bool Compiler::Execute(const char *exec, std::string *out, int *exit_code) {
1493// // int status;
1494// // pid_t pid;
1495// //
1496// // int mypipe[2];
1497// // pipe(mypipe);
1498// //
1499// // pid = fork();
1500// // if(pid < 0) {
1501// // LOG_ERROR("Fork fail");
1502// // return false;
1503// // } else if(!pid) {
1504// // close(mypipe[0]); /* close unused in */
1505// // dup2(mypipe[1], 1); /* stdout to pipe out */
1506// //
1507// // execl("/bin/bash", "bash", "-c", exec, NULL);
1508// //
1509// // close(mypipe[1]);
1510// // _exit(EXIT_SUCCESS);
1511// // }
1512// //
1513// // pid = wait(&status);
1514// //
1515// // /* parent process */
1516// // close(mypipe[1]); /* close unused out */
1517// //
1518// // char buf[1024] = "";
1519// // ssize_t nbytes;
1520// // /* read from pipe in */
1521// // while((nbytes = read(mypipe[0], buf, sizeof (buf))) > 0) {
1522// // if(out) {
1523// // out->append(buf, nbytes);
1524// // }
1525// // }
1526// // close(mypipe[0]);
1527// //
1528// // if(WIFEXITED(status)) {
1529// // if(exit_code) {
1530// //
1531// // *exit_code = WEXITSTATUS(status);
1532// // }
1533// // return true;
1534// // }
1535// return false;
1536//}
1537//
1538//llvm::ExecutionEngine * Compiler::JITCompileCPP(const char* source, const char *file_name) {
1539//
1540// std::vector<std::string> opts;
1541// opts.push_back("-x");
1542// opts.push_back("c++");
1543// opts.push_back("-std=c++14");
1544//
1545// opts.push_back("-I/usr/lib/llvm-12/lib/clang/12.0.1/include");
1546// opts.push_back("-I/usr/include/x86_64-linux-gnu/c++/10");
1547// opts.push_back("-I/usr/include/c++/10");
1548// opts.push_back("-I/usr/local/include");
1549// opts.push_back("-I/usr/include");
1550// opts.push_back("-I..");
1551//
1552// //-I/usr/lib/llvm-12/include -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS
1553// opts.push_back("-I/usr/lib/llvm-12/include");
1554// opts.push_back("-D_GNU_SOURCE");
1555// opts.push_back("-D__STDC_CONSTANT_MACROS");
1556// opts.push_back("-D__STDC_FORMAT_MACROS");
1557// opts.push_back("-D__STDC_LIMIT_MACROS");
1558// opts.push_back("-D__GCC_ATOMIC_TEST_AND_SET_TRUEVAL=1");
1559//
1560//
1561// //`llvm-config-12 --cppflags` -Wno-trigraphs -Wno-invalid-source-encoding -stdlib=libstdc++ -fsanitize=undefined-trap -fsanitize-undefined-trap-on-error -ftrap-function=abort
1562// opts.push_back("-fexceptions");
1563// opts.push_back("-fcxx-exceptions");
1564// opts.push_back("-Wno-trigraphs");
1565// opts.push_back("-Wno-invalid-source-encoding");
1566// opts.push_back("-stdlib=libstdc++");
1567//
1568// opts.push_back("-fno-rtti");
1569// opts.push_back("-ffreestanding");
1570// opts.push_back("-fno-use-cxa-atexit");
1571//
1572// opts.push_back("-Wall");
1573// opts.push_back("-Werror");
1574//
1575// opts.push_back("-Wno-error=unused-variable");
1576// opts.push_back("-Wno-error=switch");
1577//
1578// // opts.push_back("-g");
1579//
1580// if(file_name) {
1581// std::ofstream file(file_name, std::ios::trunc);
1582// file << source;
1583// file << "\n\n#include <stdio.h>\n\
1584//#include <string.h>\n\
1585//int nv_add(int a, int b) {\n\
1586// printf(\"call nv_add(%d, %d)\\n\", a, b);\n\
1587// return a + b;\n\
1588//}\n\
1589//\n\
1590//int nv_sub(int a, int b) {\n\
1591// printf(\"call nv_sub(%d, %d)\\n\", a, b);\n\
1592// return a - b;\n\
1593//}\n\
1594//";
1595// file.close();
1596//
1597// opts.push_back(file_name);
1598//
1599// } else {
1600//
1601// // Компиляция из памяти
1602// int codeInPipe[2];
1603// pipe2(codeInPipe, O_NONBLOCK);
1604// ::write(codeInPipe[1], (void *) source, strlen(source));
1605// ::close(codeInPipe[1]); // We need to close the pipe to send an EOF
1606// dup2(codeInPipe[0], STDIN_FILENO);
1607//
1608// opts.push_back("-"); // Read code from stdin
1609// }
1610//
1611// return m_jit->CompileModule(source, opts);
1612//}
1613
1614//bool Compiler::CompileModule(const char* filename, const char* output) {
1615//
1616// std::string in_data = ReadFile(filename);
1617// if(in_data.empty()) {
1618// LOG_DEBUG("Not found or empty file '%s'", filename);
1619// return false;
1620// }
1621//
1622// TermPtr term;
1623// Parser p(term);
1624// p.Parse(in_data.c_str());
1625// if(!term) {
1626// LOG_DEBUG("Fail parsing file '%s'", filename);
1627// return false;
1628// }
1629//
1630// std::string temp_name(filename);
1631// temp_name.append(".temp");
1632//
1633// std::ostringstream sstr;
1634// Context ctx(RunTime::Init());
1635// MakeCppFile(term, sstr, in_data.c_str(), &ctx);
1636//
1637// std::string file_name(temp_name);
1638// file_name.append(".cpp");
1639//
1640// std::ofstream file(file_name);
1641// file << sstr.str();
1642// file.close();
1643//
1644// return Compiler::GccMakeModule(file_name.c_str(), output);
1645//}
1646
1647
1648//std::string NewLang::MakeFunctionsHeaderSourceForJIT(TermPtr asg);
1649// if(asg->IsFunction()) {
1650// }
1651//}
1652//std::string NewLang::MakeFunctionsSourceForJIT(TermPtr asg);
1653// if(asg->IsFunction()) {
1654//
1655// } else if(asg->getTermID() == TermID::BLOCK) {
1656// ObjPtr temp;
1657// for (TermPtr &elem : calcasgBlockCode()) {
1658//
1659// }
1660// }
1661//}
1662
1663//std::string NewLang::MakeFunctionsSourceForJIT(TermPtr ast, Context *ctx) { //, const char *source) {
1664//
1665// CompileInfo ci;
1666// std::string result;
1667// std::ostringstream out;
1668//
1669// if(ctx && ctx->m_info.global) {
1670// for (auto &elem : ctx->m_info.global->m_funcs) {
1671// ci.builtin.insert(elem.first);
1672// }
1673// }
1674//
1675//
1676// WriteIncludeFiles_(out);
1677// result += out.str();
1678//
1679// // if(source) {
1680// // result += "\n//Module source\n";
1681// // result += "extern \"C\" const char * " NEWLANG_PREFIX "_module_source;\n";
1682// // result += "const char * " NEWLANG_PREFIX "_module_source=\"" << EncodeNonAsciiCharacters(source) << "\";\n\n";
1683// // }
1684//
1685// result += "//Module function declarations\n";
1686// result += NEWLANG_NS "::ObjPtr " NEWLANG_PREFIX "_main_module_func(" NEWLANG_NS "::Context *ctx, " NEWLANG_NS "::Object &in);\n";
1687//
1688// std::vector<std::string> func_list;
1689// out.str("");
1690// WriteDeclarationFunctions_(ast, out, func_list);
1691// result += out.str();
1692//
1693// result += "\n//List of module funtions\n";
1694// result += "size_t " NEWLANG_PREFIX "_func_list_count=" + std::to_string(func_list.size()) + ";\n";
1695// // result += "extern \"C\" const char * " NEWLANG_PREFIX "_func_list[" + std::to_string(func_list.size()) + "];\n";
1696// result += "const char * " NEWLANG_PREFIX "_func_list[" + std::to_string(func_list.size()) + "] = {\n";
1697// for (auto elem : func_list) {
1698// result += NEWLANG_INDENT_OP "\"" + elem + "\",\n";
1699// }
1700// result += "};\n";
1701//
1702//
1703// result += "\n//Constants form module\n";
1704// out.str("");
1705// MakeCppFileConstants(ci, ast, out);
1706// result += out.str();
1707//
1708// // result += "\n//Main function module\n";
1709// // result += NEWLANG_NS "::ObjPtr"bool " NEWLANG_PREFIX "_main_module_func(" NEWLANG_NS "::Context *ctx, " NEWLANG_NS "::Object &in, " NEWLANG_NS "::ObjPtr &out) {\n";
1710// // std::string main_module;
1711// // if(ast->getTermID() == TermID::BLOCK) {
1712// // for (TermPtr &elem : ast->BlockCode()) {
1713// // main_module += MakeCppFileMainModule(ci, elem);
1714// // }
1715// // } else {
1716// // main_module = MakeCppFileMainModule(ci, ast);
1717// // }
1718// // std::cout << main_module << "\n";
1719// // TermPtr term_empty;
1720// // ReplaceFuncObject(term_empty, main_module);
1721// // result += main_module;
1722// // result += "\n" NEWLANG_INDENT_OP "return true;\n}\n";
1723//
1724// result += "\n//Module function code\n";
1725//
1726// out.str("");
1727// MakeCppFileFunctions(ci, ast, out);
1728//
1729// result += out.str();
1730// return result;
1731//}
1732
1733//bool Compiler::GccMakeModule(const char * in_file, const char * module, const char * opts, std::string *out, int *exit_code) {
1734//
1735// //char temp[MAXPATHLEN];
1736// //if(!getcwd(temp, sizeof (temp))) {
1737// // return false;
1738// //}
1739//
1740// //std::string dir(temp);
1741//
1742// //std::string out_file(dir);
1743//
1744// //out_file.append("/");
1745// //out_file.append(module);
1746// //// out_file.append(".so");
1747//
1748// //if(!opts) {
1749// // struct stat file_src;
1750// // struct stat file_so;
1751// // if(lstat(in_file, &file_src) == 0 && lstat(out_file.c_str(), &file_so) == 0) {
1752// // if(file_src.st_mtime < file_so.st_mtime && file_so.st_size) {
1753// // LOG_DEBUG("Skip build %s", out_file.c_str());
1754// // return true;
1755// // }
1756// // }
1757// //}
1758//
1759// //std::remove(out_file.c_str());
1760//
1761//
1762// ////g++ -std=c++17 -c -g -DDEBUG -DLOG_LEVEL_NORMAL=LOG_LEVEL_DEBUG -DUNITTEST -I.. -I../contrib/googletest/googletest -I../contrib/googletest/googletest/include -MMD -MP -MF "test_gen.cpp.o.d" -o test_out.o test_gen.cpp
1763//
1764// //std::string exec("cd ");
1765// //exec.append(dir);
1766// //exec.append(" && ");
1767//
1768// //exec.append("g++ -std=c++14 -Werror=return-type -c -g -fPIC -DDEBUG -DLOG_LEVEL_NORMAL=LOG_LEVEL_DEBUG ");
1769// //if(opts) {
1770// // exec.append(opts);
1771// //}
1772// //exec.append(" -I.. -I../contrib/googletest/googletest -I../contrib/googletest/googletest/include -I../contrib/torch/include/torch/csrc/api/include -I../contrib/torch/include -MMD -MP -MF \"");
1773// //exec.append(in_file);
1774// //exec.append(".o.d\" -o ");
1775// //exec.append(in_file);
1776// //exec.append(".o ");
1777// //exec.append(in_file);
1778//
1779// //exec.append(" && ");
1780//
1781// ////g++ -o test_gen.so test_gen.o -shared -fPIC
1782// //exec.append("g++ -o ");
1783// //exec.append(out_file);
1784// //exec.append(" ");
1785// //exec.append(in_file);
1786// //exec.append(".o -shared -fPIC");
1787//
1788// //LOG_DEBUG("%s", exec.c_str());
1789//
1790// //return Execute(exec.c_str(), out, exit_code);
1791// return false;
1792//}
1793//
1794//Compiler::Compiler(RuntimePtr rt) : m_rt(rt) {
1795// if (!m_rt) {
1796// m_rt = RunTime::Init();
1797// }
1798//
1799// // m_jit = cppjit::CppJIT::Instance();
1800//}
1801
1802//ObjPtr NewLang::Eval(Context *ctx, const char *text, bool make_function) {
1803// TermPtr calc;
1804// Parser parser(calc);
1805// try {
1806// parser.Parse(text);
1807// } catch (parser_exception &ex) {
1808// return Obj::CreateError(ex.what());
1809// }
1810//
1811// char filename[] = "lazy.temp.XXXXXX";
1812// int file = mkstemp(filename);
1813// if(filename && file != -1) {
1814// write(file, text, strlen(text));
1815// close(file);
1816// } else {
1817// LOG_RUNTIME("Fail create temp file '%s'!", filename);
1818// }
1819//
1820// return ExecModule(filename, filename, true, ctx);
1821//}
1822
1823//ObjPtr NewLang::GetIndexField(Context *ctx, ObjPtr obj, TermPtr term, bool create_field) {
1824// if(!term->Right()) {
1825// return obj;
1826// } else if(term->Right()->getTermID() == TermID::FIELD && !term->Right()->Right() && create_field) {
1827// // Если последнее в списке поле создается
1828// return obj->push_back(Obj::CreateNone(), term->Right()->getText().c_str()).second;
1829// }
1830// ObjPtr result;
1831// if(term->Right()->getTermID() == TermID::FIELD) {
1832// result = (*obj)[term->Right()->m_text.c_str()].second;
1833// return GetIndexField(ctx, result, term->Right());
1834// } else if(term->Right()->getTermID() == TermID::INDEX) {
1835// result = Obj::GetIndex(obj, term->Right());
1836// return GetIndexField(ctx, result, term->Right());
1837// }
1838// LOG_RUNTIME("Fail type %s of object '%s'!", newlang::toString(term->Right()->getTermID()), term->Right()->toString().c_str());
1839//}
1840
1841//ObjPtr NewLang::Eval(Context *ctx, TermPtr calc, bool make_function) {
1842// try {
1843// if(!calc) {
1844// LOG_RUNTIME("Empty term evaluate!");
1845// }
1846//
1847// // if(calc->getTermID() == TermID::OPERATOR) {
1848// // // Все операторы в отдельной функции
1849// // return EvalOp(ctx, calc);
1850// // }
1851// // if(calc->getTermID() == TermID::ITERATOR) {
1852// // // Все операторы в отдельной функции
1853// // return EvalIter(ctx, calc);
1854// // }
1855//
1856// TermID term_id = calc->getTermID();
1857// if(calc->IsLiteral() || term_id == TermID::DICT || term_id == TermID::TUPLE) { // Константа
1858// ASSERT(calc->getTermID() != TermID::STRBYTE); // Нужно раскрыть переменные в строке
1859// return Obj::CreateFrom(ctx, calc);
1860// } else if(term_id == TermID::CALL || term_id == TermID::TERM) { // Термин или вызов функции
1861//
1862// Object args(ctx, calc, true);
1863//
1864// ObjPtr obj = Context::CallByName(ctx, calc->getText().c_str(), args, calc->isRef());
1865// return GetIndexField(ctx, obj, calc);
1866//
1867// // } else if(term_id == TermID::ITERATOR) { // Итератор
1868// // ASSERT(calc->Left());
1869// // if(calc->Left()) {
1870// // ArgPtr args = Arg::CreateObject(ctx, calc);
1871// // if(calc->m_text.compare("?") == 0) {
1872// // VERIFY(args->PrepareObject(std_args_iterator_multiple.get()));
1873// // } else if(calc->m_text.compare("?!") == 0) {
1874// // VERIFY(args->PrepareObject(std_args_iterator_single.get()));
1875// // }
1876// // ObjPtr temp;
1877// // std_iterator(Obj::CreateFrom(ctx, calc).get(), args, temp);
1878// // return temp;
1879// // }
1880// } else if(term_id == TermID::BLOCK) { // Последовательность операторов
1881// ObjPtr temp;
1882// for (TermPtr &elem : calc->BlockCode()) {
1883// temp = Eval(ctx, elem);
1884// }
1885// return temp;
1886//
1887// } else if(term_id == TermID::ITERATOR) {
1888// if(calc->m_text.compare("?") == 0) {
1889//
1890// }
1891// ObjPtr temp;
1892// for (TermPtr &elem : calc->BlockCode()) {
1893// temp = Eval(ctx, elem);
1894// }
1895// return temp;
1896//
1897// } else if(term_id == TermID::ASSIGN || term_id == TermID::APPEND || term_id == TermID::INDEX) {
1898//
1899//
1900// ObjPtr right;
1901// if(calc->Right()) {
1902// right = Eval(ctx, calc->Right(), make_function);
1903// } else {
1904// right = Obj::CreateNone();
1905// }
1906//
1907// if(term_id == TermID::APPEND) {
1908// std::string name(calc->Left()->m_text);
1909// // Если создаем сессионные или глобальные объекты
1910// if(name.compare("@") == 0 || name.compare("$") == 0) {
1911// if(calc->Left()->m_name.empty()) {
1912// ParserException("Append session or global term without name!", *calc->Left()->m_source, calc->Left()->m_line, calc->Left()->m_col);
1913// }
1914// if(name.compare("$") == 0) {
1915// return ctx->CreateSessionTerm(right, calc->Left()->m_name.c_str());
1916// } else if(name.compare("@") == 0) {
1917// return ctx->CreateGlobalTerm(right, calc->Left()->m_name.c_str());
1918// }
1919// LOG_RUNTIME("Fail logic");
1920// }
1921// }
1922// // Левый операнд всегда существует
1923// ObjPtr lval;
1924// if(term_id == TermID::APPEND) {
1925// Object args;
1926// lval = Context::CallByName(ctx, calc->Left()->m_text.c_str(), args, true);
1927// lval->push_back(right);
1928// } else {
1929// lval = Eval(ctx, calc->Left(), make_function);
1930// ASSERT(lval);
1931// lval->op_assign(right);
1932// }
1933//
1934// return lval;
1935//
1936// } else if(term_id == TermID::CREATE_NEW || term_id == TermID::CREATE_NEW || term_id == TermID::CREATE_NEW || term_id == TermID::CREATE_NEW) { // Создание нового термина
1937//
1938// // Левый операнд всегда создается
1939// ObjPtr base;
1940// ObjPtr lval;
1941// if(calc->Left()->Right()) {
1942// base = Context::CallByName(ctx, calc->Left()->getText().c_str(), Object(), true);
1943// lval = GetIndexField(ctx, base, calc->Left(), true);
1944// } else {
1945// lval = Obj::CreateNone();
1946// }
1947//
1948//
1949// ObjPtr rval = Eval(ctx, calc->Right(), make_function);
1950//
1951// lval->op_assign(rval);
1952//
1953// if(term_id == TermID::CREATE_NEW) {
1954// lval->MakeConst();
1955// }
1956// if(term_id == TermID::CREATE_NEW || term_id == TermID::CREATE_NEW) {
1957// if(lval->is_dictionary() || term_id == TermID::CREATE_NEW) {
1958// lval->m_var_name = calc->Left()->m_text;
1959// }
1960// return ctx->CreateSessionTerm(lval, calc->Left()->m_text.c_str());
1961// } else if(term_id == TermID::CREATE_NEW) {
1962// return ctx->CreateGlobalTerm(lval, calc->Left()->m_text.c_str());
1963// }
1964// return lval;
1965//
1966// } else if(term_id == TermID::SIMPLE || term_id == TermID::FUNCTION || term_id == TermID::PURE_USE) {
1967// if(!make_function) { // Игнорировать определения функций при выполнении
1968// // Ничего не делаем
1969// ObjType type;
1970// switch(term_id) {
1971// case TermID::SIMPLE:
1972// case TermID::PURE_USE:
1973// type = ObjType::PUREFUNC;
1974// break;
1975// case TermID::FUNCTION:
1976// type = ObjType::FUNCTION;
1977//
1978// break;
1979// default:
1980// LOG_RUNTIME("Function type '%s' unknown '%s'", EnumStr(calc->getTermID()).c_str(), calc->toString().c_str());
1981// }
1982// return Obj::CreateFunc(ctx, calc->Left(), type, calc->Left()->getText().c_str());
1983// }
1984//
1985// // std::string temp_name("runtime.temp");
1986// // std::ostringstream sstr;
1987// //
1988// // MakeCppFile(calc, sstr);
1989// //
1990// // std::string file_name(temp_name);
1991// // file_name.append(L".cpp");
1992// //
1993// // std::ofstream file(file_name);
1994// // file << sstr.str();
1995// // file.close();
1996// //
1997// // if(GccMakeModule(file_name.c_str(), temp_name.c_str())) {
1998// // if(ctx.m_global && ctx.m_global->LoadModule(temp_name.c_str()) && ctx.m_global->HasFunc(calc->Left()->GetFullName().c_str())) {
1999// // out = Obj::CreateValue(true);
2000// // return true;
2001// // }
2002// // }
2003// // out = Obj::CreateValue(false);
2004// // return false;
2005// }
2006//
2007// LOG_RUNTIME("Calculate type %s '%s' not implemented!", EnumStr(calc->getTermID()).c_str(), calc->m_text.c_str());
2008// } catch (std::exception &ex) {
2009// return Obj::CreateError(ex.what());
2010// }
2011//}
2012
2013
2014//void Compiler::ReplaceSourceVariable(CompileInfo &ci, size_t count, std::string &body) {
2015// std::string arg_name;
2016// std::string arg_place;
2017//
2018// for (size_t i = 0; i < count; i++) {
2019// // Заменить номер аргумента
2020// arg_name = "@$" + std::to_string(i);
2021// arg_place = "in[" + std::to_string(i) + "]";
2022// body = std::regex_replace(body, std::regex(arg_name), arg_place);
2023// }
2024//
2025// for (auto &elem : ci.arguments) {
2026// // Заменить имя аргумента
2027// arg_name = MakeName(elem.first);
2028// arg_place = "in[\"" + arg_name + "\"]";
2029// arg_name = "@$" + arg_name;
2030// body = std::regex_replace(body, std::regex(arg_name), arg_place);
2031// }
2032//}
2033//
2034//std::string Compiler::GetImpl(CompileInfo &ci, TermPtr term, std::string &output) {
2035// ASSERT(0);
2036//
2037// // ASSERT(term);
2038// // std::string result;
2039// //
2040// // std::ostringstream ostr;
2041// // std::string temp;
2042// //
2043// // std::string temp2;
2044// // std::vector<std::string> iters;
2045// // TermPtr proto;
2046// // TermPtr proto2;
2047// //
2048// // ci.last_type.clear();
2049// //
2050// // switch(term->getTermID()) {
2051// // case TermID::NUMBER:
2052// // case TermID::INTEGER:
2053// // result = "Obj::CreateValue(" + term->getText() + ")";
2054// // output += result;
2055// // return result;
2056// //
2057// // case TermID::STRCHAR:
2058// // case TermID::STRWIDE:
2059// // // Экранировать спецсимволы в символьных литералах
2060// // //Obj::CreateValue("string");
2061// // temp = std::regex_replace(term->getText(), std::regex("\n"), "\\n");
2062// // temp = std::regex_replace(temp, std::regex("\""), "@\"");
2063// // result += "Obj::CreateString(";
2064// // if(term->getTermID() == TermID::STRWIDE) {
2065// // result += "L";
2066// // }
2067// // result += "\"" + temp + "\")";
2068// // output += result;
2069// // return result;
2070// //
2071// // case TermID::CREATE_NEW:
2072// // ostr.str("");
2073// // result = MakeCppFileVariable(ci, term, ostr);
2074// // output += ostr.str();
2075// // return result;
2076// //
2077// // case TermID::ARGUMENT:
2078// // result = "in[" + std::to_string(IndexArg(term)) + "]";
2079// // output += result;
2080// // return result;
2081// //
2082// // case TermID::DICT:
2083// // temp = "";
2084// // for (int i = 0; i < term->size(); i++) {
2085// // if(!temp.empty()) {
2086// // temp += ", ";
2087// // }
2088// // temp2.clear();
2089// // GetImpl(ci, (*term)[i].second, temp2);
2090// // temp += "Obj::Arg(" + temp2;
2091// // if(!term->name(i).empty()) {
2092// // temp += ", \"" + term->name(i) + "\"";
2093// // }
2094// // temp += ")";
2095// // }
2096// // result = "Obj::CreateDict(" + temp + ")";
2097// // output += result;
2098// // return result;
2099// //
2100// // case TermID::NAME:
2101// // ASSERT(!term->getName().empty() || !term->getText().empty());
2102// //
2103// // if(term->isCall()) {
2104// // if((proto = ci.isArgument(term))) {
2105// // result = "in[\"" + MakeName(term->GetFullName()) + "\"]->Call(";
2106// // result += MakeCppFileCallArgs(ci, term, proto);
2107// // result += ")";
2108// // } else if(isLocal(term->getText().c_str()) || isModule(term->getText().c_str())) {
2109// // result = "Context::CallByName(ctx, \"";
2110// // result += term->GetFullName() + "\"";
2111// // temp = MakeCppFileCallArgs(ci, term, nullptr);
2112// // if(!temp.empty()) {
2113// // result += ", " + temp;
2114// // }
2115// // result += ")";
2116// // } else if((proto = ci.isFunction(term))) {
2117// // //Непосредственный вызов - разрешение имени во время компиляции
2118// // result = MakeLocalName(term->getText().c_str()) + "(ctx, ";
2119// // result += "Obj::CreateDict(Obj::Arg()";
2120// // temp = MakeCppFileCallArgs(ci, term, proto);
2121// // if(!temp.empty()) {
2122// // result += ", " + temp;
2123// // }
2124// // result += "))";
2125// // } else {
2126// // //Клонирование переменной - разрешение имени во время компиляции
2127// // result = MakeLocalName(term->getText().c_str()) + "->Call(";
2128// // result += MakeCppFileCallArgs(ci, term, nullptr);
2129// // result += ")";
2130// // }
2131// //
2132// // output += result;
2133// // return result;
2134// // }
2135// //
2136// //
2137// // if(term->GetFullName().compare("_") == 0) {
2138// // //Пустой объект
2139// // ci.last_type = "_";
2140// // result = "Obj::CreateNone()";
2141// // } else if(ci.isLocalAccess(term)) {
2142// // //Доступ по имени - разрешение имени во время компиляции
2143// // result = MakeLocalName(term->GetFullName().c_str());
2144// // } else if(ci.isArgument(term)) {
2145// //
2146// // result = "in[\"" + MakeName(term->GetFullName()) + "\"]";
2147// //
2148// // } else if(!term->GetFullName().empty()) {
2149// // //Вызов по имении переменной (создание копии объекта) - разрешение имени во время компиляции
2150// // result = "Context::CallByName(ctx,\"" + term->GetFullName() + "\")";
2151// // } else {
2152// // //Вызов по имении переменной (создание копии объекта) - разрешение имени во время компиляции
2153// // result = "Obj::CreateNone()";
2154// // }
2155// //
2156// // if(term->Right()) {
2157// // GetImpl(ci, term->Right(), result);
2158// // }
2159// //
2160// // output += result;
2161// // return result;
2162// //
2163// // // case TermID::FIELD:
2164// // // ASSERT(!term->getName().empty() || !term->getText().empty());
2165// // // ASSERT(!term->Right());
2166// // //
2167// // // if(!ci.m_builtin_direct->CheckDirect(ci, term, output)) {
2168// // // output.insert(0, "(*");
2169// // // output += ")[\"" + term->getText() + "\"]";
2170// // // }
2171// // // result = output;
2172// // // return result;
2173// //
2174// // case TermID::EMBED:
2175// // temp = term->getText();
2176// // ReplaceSourceVariable(ci, ci.arguments.size() + 1, temp);
2177// // output += temp;
2178// // return "";
2179// //
2180// // case TermID::INT_PLUS:
2181// // case TermID::INT_MINUS:
2182// //
2183// // if(term->m_right) {
2184// // GetImpl(ci, term->m_right, temp);
2185// // output += "return " + temp;
2186// //
2187// // } else {
2188// // output += "return Obj::CreateNone()";
2189// // }
2190// // return "";
2191// //
2192// // case TermID::ARGS:
2193// // result = "in";
2194// // output += result;
2195// // return result;
2196// //
2197// // case TermID::ASSIGN:
2198// // GetImpl(ci, term->Left(), result);
2199// // output += "(*" + result + ")=";
2200// // GetImpl(ci, term->Right(), temp);
2201// // output += temp;
2202// // return result;
2203// //
2204// // case TermID::APPEND:
2205// // GetImpl(ci, term->Left(), result);
2206// // result = result + "->push_back(";
2207// // GetImpl(ci, term->Right(), temp);
2208// // result += temp;
2209// // if(!term->m_name.empty()) {
2210// // result += ", \"" + term->m_name + "\"";
2211// // }
2212// // result += ")";
2213// // output += result;
2214// // return result;
2215// //
2216// // case TermID::OPERATOR:
2217// // proto = ci.findObject(term->Left()->GetFullName());
2218// // if(!proto) {
2219// // proto = term->Left();
2220// // }
2221// // proto2 = ci.findObject(term->Right()->GetFullName());
2222// // if(!proto2) {
2223// // proto2 = term->Right();
2224// // }
2225// // NL_TYPECHECK(term, proto2->m_type_name, proto->m_type_name);
2226// //
2227// // GetImpl(ci, term->Left(), temp2);
2228// // result = "(*" + temp2 + ")" + term->getText();
2229// // GetImpl(ci, term->Right(), temp);
2230// // result += temp + ", " + temp2;
2231// // output += result;
2232// // return result;
2233// //
2234// // case TermID::BLOCK:
2235// // for (size_t i = 0; i < term->m_block.size(); i++) {
2236// // temp.clear();
2237// // GetImpl(ci, term->m_block[i], temp);
2238// // output += ci.GetIndent() + temp + ";\n";
2239// // }
2240// // return "";
2241// //
2242// // case TermID::WHILE:
2243// // result += ci.GetIndent(-1) + "while(";
2244// //
2245// // temp.clear();
2246// // GetImpl(ci, term->Left(), temp);
2247// // result += temp + "->GetValueAsBoolean()) {\n";
2248// //
2249// // temp.clear();
2250// // GetImpl(ci, term->Right(), temp);
2251// // result += temp;
2252// //
2253// // result += ci.GetIndent(-1) + "}";
2254// // output += result;
2255// // return "";
2256// //
2257// // case TermID::ITERATOR:
2258// // ASSERT(term->Left());
2259// // result = BeginIterators(ci, term->Left(), output, iters);
2260// //
2261// // for (int i = 0; i < iters.size(); i++) {
2262// // output += ci.GetIndent(i) + "while(!" + iters[i] + ".complete()) {\n";
2263// // }
2264// //
2265// //
2266// // if(ci.isArgument(term->Left())) {
2267// // temp = "in[\"" + MakeName(term->Left()->GetFullName()) + "\"]->Call(";
2268// // temp += MakeIteratorCallArgs_(ci, term->Left(), iters);
2269// // temp += ")";
2270// // } else if(isLocal(term->Left()->getText().c_str()) || isModule(term->Left()->getText().c_str())) {
2271// // temp = "Context::CallByName(ctx, \"";
2272// // temp += term->GetFullName() + "\"";
2273// // temp2 = MakeIteratorCallArgs_(ci, term->Left(), iters);
2274// // if(!temp2.empty()) {
2275// // temp += ", " + temp2;
2276// // }
2277// // temp += ")";
2278// // } else if(ci.isFunction(term->Left())) {
2279// // //Непосредственный вызов - разрешение имени во время компиляции
2280// // temp = MakeLocalName(term->Left()->getText().c_str()) + "(ctx, ";
2281// // temp += "Obj::CreateDict(Obj::Arg()";
2282// // temp2 = MakeIteratorCallArgs_(ci, term->Left(), iters);
2283// // if(!temp2.empty()) {
2284// // temp += ", " + temp2;
2285// // }
2286// // temp += "))";
2287// // } else {
2288// // //Клонирование переменной - разрешение имени во время компиляции
2289// // temp = MakeLocalName(term->Left()->getText().c_str()) + "->Call(";
2290// // temp += MakeIteratorCallArgs_(ci, term->Left(), iters);
2291// // temp += ")";
2292// // }
2293// //
2294// // output += ci.GetIndent(iters.size()) + "ObjPtr " + result + "_eval";
2295// // output += "=" + temp + ";\n";
2296// //
2297// // output += ci.GetIndent(iters.size()) + "if(" + result + "_eval->GetValueAsBoolean()){\n";
2298// //
2299// // for (size_t i = 0; i < iters.size(); i++) {
2300// // // (*humans)->RefInc();
2301// // output += ci.GetIndent(iters.size()) + "(*" + iters[i] + ")->RefInc();\n";
2302// // }
2303// // // output += ci.GetIndent(iters.size()) + result + "->push_back(Obj::CreateArray(*" + iters[0] + ", *" + iters[1] + "));\n";
2304// // output += ci.GetIndent(iters.size() + 1) + result + "->push_back(Obj::CreateArray(";
2305// // for (size_t i = 0; i < iters.size(); i++) {
2306// // if(i) {
2307// // output += ", ";
2308// // }
2309// // output += "*" + iters[i];
2310// // }
2311// // output += "));\n";
2312// //
2313// // output += ci.GetIndent(iters.size()) + "}\n";
2314// //
2315// //
2316// // for (size_t i = iters.size() - 1; i > 0; i--) {
2317// // output += ci.GetIndent(i + 1) + iters[i] + "++;\n";
2318// // output += ci.GetIndent(i) + "}\n";
2319// // if(i) {
2320// // output += ci.GetIndent(i) + iters[i] + ".reset();\n";
2321// // output += ci.GetIndent(i) + iters[i - 1] + "++;\n";
2322// // }
2323// // }
2324// // output += ci.GetIndent() + "}";
2325// //
2326// // return result;
2327// //
2328// // }
2329// // if(term->getTermID() == TermID::FOLLOW) {
2330// // bool else_if = false;
2331// // for (size_t i = 0; i < term->m_follow.size(); i++) {
2332// //
2333// // if(else_if && term->m_follow[i]->Left()) {
2334// // result += " else ";
2335// // } else {
2336// // else_if = true;
2337// // }
2338// //
2339// // if(term->m_follow[i]->Left()) {
2340// // temp.clear();
2341// // GetImpl(ci, term->m_follow[i]->Left(), temp);
2342// // result += ci.GetIndent() + "if((" + temp + ")->GetValueAsBoolean()) {";
2343// // } else {
2344// // if(i == 0 || i != term->m_follow.size() - 1) {
2345// // LOG_RUNTIME("Bad logic follow '%s'", term->toString().c_str());
2346// // }
2347// // result += " else {";
2348// // }
2349// // if(term->m_follow[i]->Right()) {
2350// // temp.clear();
2351// // GetImpl(ci, term->m_follow[i]->Right(), temp);
2352// // result += "\n" NEWLANG_INDENT_OP + ci.GetIndent() + temp + ";\n" + ci.GetIndent() + "}";
2353// // } else {
2354// // LOG_RUNTIME("Bad logic follow '%s'", term->toString().c_str());
2355// // }
2356// // }
2357// // result += "\n";
2358// // output += result;
2359// // return "";
2360// // }
2361//
2362// LOG_RUNTIME("Can`t term type '%s' implementation '%s'!", newlang::toString(term->getTermID()), term->toString().c_str());
2363//}
2364//
2365//std::string Compiler::MakeIteratorCallArgs_(CompileInfo &ci, TermPtr args, std::vector<std::string> &iters) {
2366// std::string result;
2367// size_t iter_pos = 0;
2368//
2369// for (int i = 0; i < args->size(); i++) {
2370// std::string impl;
2371//
2372// if (i) {
2373// result += ", ";
2374// }
2375//
2376// if (args->at(i).second->getTermID() == TermID::ITERATOR) {
2377// ASSERT(args->at(i).second->Left());
2378// if (args->at(i).second->getText().compare("!") == 0) {
2379// ASSERT(iter_pos < iters.size());
2380// impl = "*" + iters[iter_pos];
2381// } else {
2382// LOG_RUNTIME("Iterator '%s' not implemented!", args->at(i).second->getText().c_str());
2383// }
2384//
2385// if (args->at(i).first.empty()) {
2386// result += "Obj::Arg(" + impl + ")";
2387// } else {
2388// result += "Obj::Arg(" + impl + ", \"" + args->at(i).first + "\")";
2389// }
2390//
2391// iter_pos++;
2392//
2393// } else {
2394//
2395// GetImpl(ci, args->at(i).second, impl);
2396// if (args->at(i).first.empty()) {
2397// result += "Obj::Arg(" + impl + ")";
2398// } else {
2399// result += "Obj::Arg(" + impl + ", \"" + args->at(i).first + "\")";
2400// }
2401// }
2402// }
2403// return result;
2404//}
2405//
2406//std::string Compiler::BeginIterators(CompileInfo &ci, TermPtr args, std::string &output, std::vector<std::string> &iters) {
2407//
2408// std::string summary = "summary";
2409// output += ci.GetIndent() + "ObjPtr " + summary + "=Obj::CreateArray();\n";
2410//
2411// // Аргументы функции с локальным доступом по имени или ииндексу
2412// if (args->size()) {
2413// for (int i = 0; i < args->size(); i++) {
2414// if ((*args)[i].second->getTermID() == TermID::ITERATOR) {
2415// std::string name;
2416// if ((*args)[i].second->getText().compare("!") == 0) {
2417//
2418// ASSERT((*args)[i].second->Left());
2419// ASSERT(!(*args)[i].second->size()); // todo пока без обработки аргументов
2420//
2421// name = "iter_" + std::to_string(i + 1);
2422// iters.push_back(name);
2423// output += ci.GetIndent() + "auto " + name + "= ctx->m_info.global->select(\"" + (*args)[i].second->Left()->getText() + "\");\n";
2424// } else {
2425// LOG_RUNTIME("Iterator '%s' not implemented!", (*args)[i].second->getText().c_str());
2426// }
2427// }
2428// }
2429// }
2430// return summary;
2431//}
2432
2433LLVMGenericValueRef GetGenericValueRef(Obj &obj, LLVMTypeRef type) {
2434 if (type == LLVMInt1Type() || type == LLVMInt8Type() || type == LLVMInt16Type() || type == LLVMInt32Type() || type == LLVMInt64Type()) {
2435 return LLVMCreateGenericValueOfInt(type, obj.GetValueAsInteger(), true);
2436 } else if (type == LLVMFloatType() || type == LLVMDoubleType()) {
2437 return LLVMCreateGenericValueOfFloat(type, obj.GetValueAsNumber());
2438 } else if (type == LLVMPointerType(LLVMInt8Type(), 0)) {
2439 if (obj.getType() == ObjType::StrChar || obj.getType() == ObjType::FmtChar) {
2440 return LLVMCreateGenericValueOfPointer((void *) obj.m_value.c_str());
2441 } else if (obj.getType() == ObjType::Pointer) {
2442 ASSERT(std::holds_alternative<void *>(obj.m_var));
2443 return LLVMCreateGenericValueOfPointer(std::get<void *>(obj.m_var));
2444 }
2445 } else if (type == LLVMPointerType(LLVMInt32Type(), 0)) {
2446 if (obj.getType() == ObjType::StrWide || obj.getType() == ObjType::FmtWide) {
2447
2448 return LLVMCreateGenericValueOfPointer((void *) obj.m_string.c_str());
2449 }
2450 }
2451 LOG_RUNTIME("Not support LLVM type '%s'", newlang::toString(obj.m_var_type_current));
2452}
2453
2454ObjPtr CreateFromGenericValue(ObjType type, LLVMGenericValueRef ref, LLVMTypeRef llvm_type) {
2455 if (type == ObjType::None) {
2456 return Obj::CreateNone();
2457 } else if (isIntegralType(type, true)) {
2458 int64_t value = LLVMGenericValueToInt(ref, true);
2459 unsigned width = LLVMGenericValueIntWidth(ref);
2460 return Obj::CreateValue(value, type);
2461 } else if (isFloatingType(type)) {
2462 return Obj::CreateValue((double) LLVMGenericValueToFloat(llvm_type, ref), type);
2463 } else if (type == ObjType::StrChar || type == ObjType::FmtChar) {
2464 if (llvm_type == LLVMInt8Type()) {
2465 return Obj::CreateString(std::string(1, (char) LLVMGenericValueToInt(ref, false)));
2466 } else {
2467 //@todo Нужна проверка на тип LLVM данных?
2468 return Obj::CreateString(std::string((const char *) LLVMGenericValueToPointer(ref)));
2469 }
2470 } else if (type == ObjType::StrWide || type == ObjType::FmtWide) {
2471 if (llvm_type == LLVMInt32Type()) {
2472 return Obj::CreateString(std::wstring(1, (wchar_t) LLVMGenericValueToInt(ref, false)));
2473 } else {
2474 //@todo Нужна проверка на тип LLVM данных?
2475 return Obj::CreateString(std::wstring((const wchar_t *)LLVMGenericValueToPointer(ref)));
2476 }
2477 } else if (type == ObjType::Pointer) {
2478
2480 result->m_var = LLVMGenericValueToPointer(ref);
2481
2482 return result;
2483 }
2484 LOG_RUNTIME("Create to type '%s' form LLVM type not implemented!", newlang::toString(type));
2485}
2486
2487LLVMTypeRef toLLVMType(ObjType t, bool none_if_error) {
2488 switch (t) {
2489 case ObjType::None:
2490 return LLVMVoidType();
2491 case ObjType::Bool:
2492 return LLVMInt1Type();
2493 case ObjType::Int8:
2494 case ObjType::Char:
2495 case ObjType::Byte:
2496 return LLVMInt8Type();
2497 case ObjType::Int16:
2498 case ObjType::Word:
2499 return LLVMInt16Type();
2500 case ObjType::Int32:
2501 case ObjType::DWord:
2502 return LLVMInt32Type();
2503 case ObjType::Int64:
2504 case ObjType::DWord64:
2505 case ObjType::Integer:
2506 return LLVMInt64Type();
2507 case ObjType::Float32:
2508 case ObjType::Single:
2509 case ObjType::Tensor:
2510 return LLVMFloatType();
2511 case ObjType::Float64:
2512 case ObjType::Double:
2513 case ObjType::Number:
2514 return LLVMDoubleType();
2515
2516 case ObjType::Pointer:
2517 case ObjType::StrChar:
2518 case ObjType::FmtChar:
2519 return LLVMPointerType(LLVMInt8Type(), 0);
2520
2521#ifdef _MSC_VER
2522 case ObjType::StrWide:
2523 case ObjType::FmtWide:
2524 return LLVMPointerType(LLVMInt16Type(), 0);
2525#else
2526 case ObjType::StrWide:
2527 case ObjType::FmtWide:
2528 return LLVMPointerType(LLVMInt32Type(), 0);
2529#endif
2530
2531 }
2532 LOG_RUNTIME("Can`t convert type '%s' to LLVM type!", toString(t));
2533}
2534
2536 // @todo Сделать корректныую очистку состояния парсера???
2537 return std::make_shared<Parser>(m_macro, nullptr, m_diag, true, this);
2538}
2539
2540ObjPtr JIT::RunFile(std::string file, Obj* args) {
2541 if (!RunTime::ExpandFileName(file)) {
2542 LOG_RUNTIME("File or module '%s' not found!", file.c_str());
2543 }
2544 std::string source = ReadFile(file.c_str());
2545 // TermPtr ast = MakeAst(source);
2546 // if (args) {
2547 // args->insert(args->begin(), {
2548 // "", Obj::CreateString(file)
2549 // });
2550 // }
2551 return Run(source, args);
2552}
2553
2554/*
2555 * Построчное выполнение не изменяет AST, а только добавляет к нему новые строки.
2556 * Констекст выполнения (m_main_runner) тоже остается не изменным.
2557 */
2558ObjPtr JIT::Run(const std::string_view str, Obj* args) {
2559
2560 if (m_module.empty()) {
2562 m_module.push_back(std::make_shared<Module>(this, m_main_ast));
2563 }
2564 if (m_ctx.empty()) {
2565 m_ctx.push_back(std::make_shared<Context>(this));
2566 }
2567
2569
2570 TermPtr temp = GetParser()->Parse(str.begin());
2571 ASSERT((*m_module.begin())->m_ast);
2572 {
2573 SCOPE_LOCK_WRITE(this);
2574 TermPtr *ast = reinterpret_cast<TermPtr *> (&(*m_module.begin())->m_ast);
2575 ASSERT(ast);
2576 (*ast)->m_block.push_back(temp);
2577 }
2578
2579
2580 try {
2581 m_diag->m_error_count = 0;
2582
2583 AstAnalysis analysis(*this, m_diag.get());
2584
2585 analysis.Analyze((*m_module.begin())->m_ast->m_block.back(), &m_stack);
2586
2587 if (m_diag->m_error_count) {
2588 LOG_PARSER("fatal error: %d generated. ", m_diag->m_error_count);
2589 }
2590
2591 result = Context::Execute(*(*m_module.begin()), (*m_module.begin())->m_ast->m_block.back(), &GetCtx()).GetVariablePair(true).var.GetValueAsObject();
2592
2593 } catch (...) {
2594
2595 SCOPE_LOCK_WRITE(this);
2596 TermPtr *ast = reinterpret_cast<TermPtr *> (&(*m_module.begin())->m_ast);
2597 ASSERT(ast);
2598 (*ast)->m_block.pop_back();
2599
2600 throw;
2601 }
2602 return result;
2603}
2604
2605ObjPtr JIT::Run(Module *module, Obj* args) {
2606 LOG_RUNTIME("Run module not implemented!");
2607 return nullptr;
2608}
2609
2610//TermPtr JIT::MakeAstParser(const std::string_view src, bool skip_analize) {
2611// TermPtr ast = GetParser()->Parse(src.begin());
2612// if (skip_analize) {
2613// return ast;
2614// }
2615//
2616// AstAnalysis analysis(*this, m_diag.get());
2617//
2618// if (!analysis.Analyze(ast, ast)) {
2619// LOG_RUNTIME("Make AST fail!");
2620// }
2621// return ast;
2622//}
2623//
2624//TermPtr JIT::MakeAst(const std::string_view src, bool skip_analize) {
2625// TermPtr ast = Parser::ParseString(src.begin());
2626// if (skip_analize) {
2627// return ast;
2628// }
2629//
2630// AstAnalysis analysis(*this, m_diag.get());
2631//
2632// if (!analysis.Analyze(ast, ast)) {
2633// LOG_RUNTIME("Make AST fail!");
2634// }
2635// return ast;
2636//}
2637
2638bool JIT::ModuleCreate(FileModule &data, const std::string_view source) {
2639
2640 // TermPtr ast = MakeAst(source, false);
2641 return false;
2642}
2643
2644bool JIT::ModuleCreate(FileModule &data, const std::string_view module_name, const TermPtr &include, const std::string_view source, llvm::Module *bc) {
2645
2646 data.name.assign(module_name);
2647 data.include = AstAnalysis::MakeInclude(include);
2648 data.source = source;
2649 if (bc) {
2650 llvm::raw_string_ostream code(data.bytecode);
2651 llvm::WriteBitcodeToFile(*bc, code);
2652 }
2653 return !data.name.empty() && !data.include.empty() && (data.source.empty() || data.bytecode.empty());
2654}
2655
2656JIT::JIT(const StringArray &args) : RunTime(args), m_external(), m_stack(*this, m_external), m_macro(std::make_shared<Macro>()) { //m_rt(rt),
2657
2659
2660 m_repl_count = 0;
2661 // Диагностика работы Clang
2662 DiagOpts = new clang::DiagnosticOptions;
2663 textDiagPrinter = new clang::TextDiagnosticPrinter(llvm::outs(), &*DiagOpts);
2664 pDiagnosticsEngine = new clang::DiagnosticsEngine(pDiagIDs, &*DiagOpts, textDiagPrinter);
2665
2666
2667 if (m_load_dsl) {
2668
2669 VERIFY(CreateMacro("@@ true @@ ::= 1"));
2670 VERIFY(CreateMacro("@@ yes @@ ::= 1"));
2671 VERIFY(CreateMacro("@@ false @@ ::= 0"));
2672 VERIFY(CreateMacro("@@ no @@ ::= 0"));
2673
2674 VERIFY(CreateMacro("@@ if( ... ) @@ ::= @@ [ @$... ] --> @@"));
2675 VERIFY(CreateMacro("@@ elif( ... ) @@ ::= @@ ,[ @$... ] --> @@"));
2676 VERIFY(CreateMacro("@@ else @@ ::= @@ ,[...] --> @@"));
2677
2678 VERIFY(CreateMacro("@@ while( ... ) @@ ::= @@ [ @$... ] <-> @@"));
2679 VERIFY(CreateMacro("@@ dowhile( ... ) @@ ::= @@ <-> [ @$... ] @@"));
2680 VERIFY(CreateMacro("@@ loop @@ ::= @@ [ 1 ] <-> @@"));
2681
2682
2683 VERIFY(CreateMacro("@@ break $label @@ ::= @@ @$label :: ++ @@"));
2684 VERIFY(CreateMacro("@@ continue $label @@ ::= @@ @$label :: -- @@"));
2685 VERIFY(CreateMacro("@@ return $... @@ ::= @@ $:: ++ @$... ++ @@"));
2686 VERIFY(CreateMacro("@@ throw $... @@ ::= @@ -- @$... -- @@"));
2687
2688 VERIFY(CreateMacro("@@ match( ... ) @@ ::= @@ [ @$... ] @__PRAGMA_EXPECTED__( @\\ =>, @\\ ==>, @\\ ===>, @\\ ~>, @\\ ~~>, @\\ ~~~> ) @@"));
2689 VERIFY(CreateMacro("@@ case( ... ) @@ ::= @@ [ @$... ] --> @@"));
2690 VERIFY(CreateMacro("@@ default @@ ::= @@ [...] --> @@"));
2691
2692
2693 VERIFY(CreateMacro("@@ this @@ ::= @@ $0 @@ ##< This object (self)"));
2694 VERIFY(CreateMacro("@@ self @@ ::= @@ $0 @@ ##< This object (self)"));
2695 VERIFY(CreateMacro("@@ super @@ ::= @@ $$ @@ ##< Super (parent) class or function"));
2696 VERIFY(CreateMacro("@@ latter @@ ::= @@ $^ @@ ##< Result of the last operation"));
2697
2698
2699 VERIFY(CreateMacro("@@ try @@ ::= @@ [ {* @__PRAGMA_EXPECTED__( @\\ { ) @@"));
2700 VERIFY(CreateMacro("@@ catch(...) @@ ::= @@ *} ] : < @$... > ~> @@"));
2701 VERIFY(CreateMacro("@@ forward @@ ::= @@ +- $^ -+ @@ ##< Forward latter result or exception"));
2702
2703
2704 VERIFY(CreateMacro("@@ iter( obj, ... ) @@ ::= @@ @$obj ? (@$...) @@"));
2705 VERIFY(CreateMacro("@@ next( obj, ... ) @@ ::= @@ @$obj ! (@$...) @@"));
2706 VERIFY(CreateMacro("@@ curr( obj ) @@ ::= @@ @$obj !? @@"));
2707 VERIFY(CreateMacro("@@ first( obj ) @@ ::= @@ @$obj !! @@"));
2708 VERIFY(CreateMacro("@@ all( obj ) @@ ::= @@ @$obj ?? @@"));
2709
2710 VERIFY(CreateMacro("@@ and @@ ::= @@ && @@"));
2711 VERIFY(CreateMacro("@@ or @@ ::= @@ || @@"));
2712 VERIFY(CreateMacro("@@ xor @@ ::= @@ ^^ @@"));
2713 VERIFY(CreateMacro("@@ not(value) @@ ::= @@ (:Bool(@$value)==0) @@"));
2714
2715 // VERIFY(CreateMacro("@@ root() @@ ::= @@ @# @\\\\ @@"));
2716 // VERIFY(CreateMacro("@@ module() @@ ::= @@ @# $\\\\ @@"));
2717
2718 // VERIFY(CreateMacro("@@ namespace() @@ ::= @@ @# @:: @@"));
2719 VERIFY(CreateMacro("@@ module() @@ ::= @@ @$$ @@"));
2720 VERIFY(CreateMacro("@@ static @@ ::= @@ @:: @@"));
2721 VERIFY(CreateMacro("@@ package $name @@ ::= @@ @$$ = @# @$name @@"));
2722 VERIFY(CreateMacro("@@ declare( obj ) @@ ::= @@ @$obj ::= ... @@ ##< Forward declaration of the object"));
2723
2724 VERIFY(CreateMacro("@@ using(...) @@ ::= @@ ... = @$... @@"));
2725
2726 VERIFY(CreateMacro("@@ typedef(cnt) @@ ::= @@ @__PRAGMA_TYPE_DEFINE__(@$cnt) @@ ##< Disable warning when defining a type inside a namespace"));
2727
2728 VERIFY(CreateMacro("@@ coroutine @@ ::= @@ __ANNOTATION_SET__(coroutine) @@"));
2729 VERIFY(CreateMacro("@@ co_yield $val @@ ::= @@ __ANNOTATION_CHECK__(coroutine) $:: :: -- @$val -- @@"));
2730 VERIFY(CreateMacro("@@ co_await @@ ::= @@ __ANNOTATION_CHECK__(coroutine) $:: :: +- @@"));
2731 VERIFY(CreateMacro("@@ co_return $val @@ ::= @@ __ANNOTATION_CHECK__(coroutine) $:: :: ++ @$val ++ @@"));
2732
2733 VERIFY(CreateMacro("@@ exit(code) @@ ::= @@ :: ++ @$code ++ @@"));
2734 VERIFY(CreateMacro("@@ abort() @@ ::= @@ :: -- @@"));
2735
2736 /*
2737 * @time call(123);
2738 * {
2739 * __start_point__ := ::Base::microsec_point();
2740 * call(123);
2741 * ::Base::microsec_point( __start_point__ );
2742 * }
2743 */
2744 VERIFY(CreateMacro("@@ timeit( call, ... ) @@ ::= @@ { __start_point__ := ::Base::__timeit__(); @$call ; ::Base::__timeit__( __start_point__, @# @$call, @$... ); } @@ ##< Measure execution time of function call"));
2745
2746 }
2747
2748
2749 // @assert(value, ...)
2750 // @static_assert(value, ...)
2751 // @verify(value, ...)
2752 //
2753 // @__PRAGMA_ASSERT__( is_runtime, is_always, value, val_string, ... )
2754 //
2755 // @@ static_assert(value, ...) @@ ::= @@ @__PRAGMA_ASSERT__(0, 0, value, @# value, @$... ) @@;
2756 // @@ assert(value, ...) @@ ::= @@ @__PRAGMA_ASSERT__(1, 0, value, @# value, @$... ) @@;
2757 // @@ verify(value, ...) @@ ::= @@ @__PRAGMA_ASSERT__(1, 1, value, @# value, @$... ) @@;
2758
2759 // // @__PRAGMA_ASSERT__ replase to __pragma_assert__ in @ref Parser::PragmaEval
2760 // // @__PRAGMA_STATIC_ASSERT__
2761 // CALSS_METHOD(Base, __assert_abort__);
2762 // VERIFY(CreateMethod("__assert_abort__(...):None", __assert_abort__));
2763
2764 VERIFY(CreateMacro("@@ static_assert(...) @@ ::= @@ @__PRAGMA_STATIC_ASSERT__(@$... ) @@"));
2765
2766 if (m_assert_enable) {
2767 VERIFY(CreateMacro("@@ assert(value, ...) @@ ::= @@ [:Bool(@$value)==0]-->{ ::Base::__assert_abort__(@# @$value, @$value, @$... ) } @@"));
2768 VERIFY(CreateMacro("@@ verify(value, ...) @@ ::= @@ [:Bool(@$value)==0]-->{ ::Base::__assert_abort__(@# @$value, @$value, @$... ) } @@"));
2769 } else {
2770 VERIFY(CreateMacro("@@ assert(value, ...) @@ ::= @@ (_) @@"));
2771 VERIFY(CreateMacro("@@ verify(value, ...) @@ ::= @@ (@$value) @@"));
2772 }
2773}
2774
2775//ObjPtr newlang::JitLastResult(ObjPtr val) {
2776// JIT * jit = JIT::Instance();
2777// if (val) {
2778// jit->m_latter = val;
2779// }
2780// return jit->m_latter;
2781//}
2782
2783bool JIT::CreateMacro(const std::string_view text) {
2784 TermPtr m = Parser::ParseTerm(text.begin(), m_macro, false);
2785 return true;
2786}
2787
2788/* Override *weak* Logger method for print call stack by PrintStackTrace */
2790 std::string result("\n");
2791 llvm::raw_string_ostream stack(result);
2792 llvm::sys::PrintStackTrace(stack, 1);
2793 return result;
2794}
2795
2796void * RunTime::GetNativeAddress(void * handle, const std::string_view name) {
2797 LLVMLoadLibraryPermanently(nullptr);
2798 return LLVMSearchForAddressOfSymbol(name.begin());
2799}
2800
2801/*
2802 *
2803 *
2804 *
2805 *
2806 *
2807 */
2808
2809//TermPtr JIT::GetObject(const std::string_view int_name) {
2810//
2811// // std::string int_name;
2812// // if (isInternalName(int_name)) {
2813// // }
2814// // int_name = NormalizeName(int_name);
2815// // ASSERT();
2816// //
2817// // std::string int_name;
2818// //
2819// // if (term->isNone()) {
2820// // term->m_normalized = "_";
2821// // }
2822// if (int_name.empty()) {
2823// LOG_RUNTIME("Has no internal name! AST analysis required!");
2824// }
2825//
2826// TermPtr result;
2827// if (int_name.compare("_") == 0) {
2828// result = Term::CreateNone();
2829// } else if (int_name.compare("$^") == 0) {
2830// result = Term::CreateNone();
2831// result->m_obj = m_latter;
2832// } else {
2833// auto found = find(int_name.begin());
2834// if(found != end()){
2835// result = found->second.item;
2836// }
2838// if (!result && m_rt && (isGlobalScope(int_name) || isTypeName(int_name))) {
2839// result = m_rt->GlobFindProto(int_name);
2840// }
2841// }
2842// if (!result) {
2843// //#ifdef BUILD_UNITTEST
2844// // if (term->m_text.compare("__STAT_RUNTIME_UNITTEST__") == 0) {
2845// // ASSERT(term->isCall());
2846// // ASSERT(term->size() == 2);
2847// // return Obj::CreateValue(m_rt->__STAT_RUNTIME_UNITTEST__(
2848// // parseInteger(term->at(0).second->m_text.c_str()),
2849// // parseInteger(term->at(1).second->m_text.c_str())));
2850// // }
2851// //#endif
2852// LOG_RUNTIME("Object with internal name '%s' not found!", int_name.begin());
2853// }
2854//
2855// return result;
2856//}
2857//
2858//ObjPtr JIT::EvalCreate_(TermPtr & op) {
2859// ASSERT(op);
2860// ASSERT(op->isCreate());
2861// ASSERT(op->m_left);
2862//
2863// ArrayTermType l_vars = op->m_left->CreateArrayFromList();
2864//
2865// bool is_ellipsis = false;
2866// TermPtr var_found;
2867// for (auto &elem : l_vars) {
2868//
2869// if (elem->getTermID() == TermID::ELLIPSIS) {
2870//
2871// //@todo добавить поддержку многоточия с левой стороный оператора присвоения
2872// // NL_PARSER(elem, "Ellipsis on the left side in assignment not implemented!");
2873//
2874// // Игнорировать несколько объектов
2875// elem->m_obj = getEllipsysObj();
2876// if (is_ellipsis) {
2877// NL_PARSER(elem, "Multiple ellipsis on the left side of the assignment!");
2878// }
2879// is_ellipsis = true;
2880//
2881// } else if (elem->isNone()) {
2882//
2883// // Игнорировать один объект
2884// elem->m_obj = getNoneObj();
2885//
2886// } else {
2887//
2888// var_found = GetObject(elem->m_normalized);
2889//
2890// if (op->isCreateOnce() && var_found && var_found->m_obj) {
2891// NL_PARSER(elem, "Object '%s' already exist", elem->m_text.c_str());
2892// } else if (op->getTermID() == TermID::ASSIGN && !(var_found && var_found->m_obj)) {
2893// NL_PARSER(elem, "Object '%s' not exist!", elem->m_text.c_str());
2894// }
2895//
2896// if (var_found) {
2897// if (var_found->isCall() && var_found->m_obj) {
2898// NL_PARSER(elem, "The function cannot be overridden! '%s'", var_found->toString().c_str());
2899// }
2900// elem = var_found;
2901// // elem->m_normalized = var_found->m_normalized;
2902// // elem->m_obj = var_found->m_obj;
2903// // LOG_TEST("0: %s = %s (%p)", elem->m_text.c_str(), elem->m_obj ? elem->m_obj->toString().c_str() : "nullptr", elem->m_obj.get());
2904// }
2905// }
2906// }
2907//
2908// m_latter = AssignVars_(l_vars, op->m_right, op->isPure());
2909// for (auto &elem : l_vars) {
2910//
2911// // LOG_TEST("4: %s = %s (%p)", elem->m_text.c_str(), elem->m_obj ? elem->m_obj->toString().c_str() : "nullptr", elem->m_obj.get());
2912//
2913// if (isGlobalScope(elem->m_normalized)) {
2914// m_rt->NameRegister(op->isCreateOnce(), elem->m_normalized.c_str(), elem, elem->m_obj);
2915// }
2916// }
2917// return m_latter;
2918//}
2919//
2920//ObjPtr JIT::AssignVars_(ArrayTermType &l_vars, const TermPtr &r_term, bool is_pure) {
2921//
2922// ASSERT(l_vars.size());
2923// if (r_term->getTermID() == TermID::NATIVE) {
2924//
2925// ASSERT(l_vars.size() == 1);
2926// // ASSERT(vars[0]->m_obj);
2927// // ASSERT(r_term->m_obj);
2928//
2929// l_vars[0]->m_obj = m_rt->CreateNative(l_vars[0], nullptr, false, r_term->m_text.substr(1).c_str());
2930// // vars[0]->m_obj = r_term->m_obj;
2931// m_latter = l_vars[0]->m_obj;
2932//
2933// } else if (r_term->getTermID() == TermID::ELLIPSIS) {
2934// // При раскрытии словаря присвоить значение можно как одному, так и сразу нескольким терминам:
2935// // var1, var2, _ = ... func(); Первый и второй элементы записывается в var1 и var2,
2936// // а все остальные игнорируются (если они есть)
2937// // var1, var2 = ... func(); Если функция вернула словарь с двумя элементами,
2938// // то их значения записываются в var1 и var2. Если в словаре было больше двух элементов,
2939// // то первый записывается в var1, а все оставшиеся элементы в var2. !!!!!!!!!!!!!
2940// // item, dict = ... dict; Первый элементы записывается в item и удаялется из dict
2941//
2942// // _, var1, ..., var2 = ... func();
2943// // Первый элемент словаря игнорируется, второй записывается в var1, а последний в var2.
2944//
2945// //@todo добавить поддержку многоточия с левой стороный оператора присвоения
2946//
2947// bool is_named = !!r_term->m_left;
2948// if (is_named) {
2949// NL_PARSER(r_term, "Named ELLIPSIS NOT implemented!");
2950// ASSERT(r_term->m_left->getTermID() == TermID::ELLIPSIS);
2951// }
2952//
2953// bool is_last = false;
2954// ObjPtr right_obj = CheckObjTerm_(r_term->m_right, this);
2955// for (size_t i = 0; i < l_vars.size(); i++) {
2956// if (l_vars[i]->isNone()) {
2957// // Ignore position
2958// continue;
2959// }
2960// if (i + 1 == l_vars.size()) {
2961// is_last = true;
2962// }
2963//
2964// // LOG_TEST("1: %s = %s (%p)", l_vars[i]->m_text.c_str(), l_vars[i]->m_obj ? l_vars[i]->m_obj->toString().c_str() : "nullptr", l_vars[i]->m_obj.get());
2965//
2966// if (i < right_obj->size()) {
2967// if (is_last) {
2968// if (l_vars[i]->m_normalized.compare(r_term->m_right->m_normalized) == 0) {
2969// // Остаток элементов присваивается тому же словарю
2970// l_vars[i]->m_obj = right_obj;
2971// } else {
2972// l_vars[i]->m_obj = right_obj->Clone();
2973// }
2974// l_vars[i]->m_obj->erase(0, l_vars.size() - 1);
2975// } else {
2976// l_vars[i]->m_obj = (*right_obj)[i].second;
2977// }
2978// } else {
2979// if (is_last) {
2980// if (l_vars[i]->m_normalized.compare(r_term->m_right->m_normalized) == 0) {
2981// // Остаток элементов присваивается тому же словарю
2982// l_vars[i]->m_obj = right_obj;
2983// } else {
2984// l_vars[i]->m_obj = right_obj->Clone();
2985// }
2986// l_vars[i]->m_obj->erase(0, 0);
2987// } else {
2988// l_vars[i]->m_obj = Obj::CreateNone();
2989// }
2990// }
2991// // LOG_TEST("2: %s = %s (%p)", l_vars[i]->m_text.c_str(), l_vars[i]->m_obj ? l_vars[i]->m_obj->toString().c_str() : "nullptr", l_vars[i]->m_obj.get());
2992// }
2993// m_latter = l_vars[l_vars.size() - 1]->m_obj;
2994//
2995// } else if (r_term->getTermID() == TermID::FILLING) {
2996// // Заполнение переменных значениями последовательным вызовом фукнции?
2997//
2998// //@todo добавить поддержку многоточия с левой стороный оператора присвоения
2999// NL_PARSER(r_term, "FILLING NOT implemented!");
3000//
3001// } else if (r_term->isBlock()) {
3002//
3003// if (l_vars.size() > 1) {
3004// //@todo добавить поддержку присвоения сразу нескольким функциям
3005// NL_PARSER(r_term, "Multiple function assignment not implemented!");
3006// }
3007// ASSERT(l_vars.size() == 1);
3008//
3009// if (!l_vars[0]->isCall()) {
3010// NL_PARSER(l_vars[0], "Function name expected!");
3011// }
3012//
3013// ASSERT(!l_vars[0]->m_right);
3014//
3015// l_vars[0]->m_obj = m_rt->CreateFunction(l_vars[0], r_term);
3016// m_latter = l_vars[0]->m_obj;
3017//
3018// } else {
3019//
3020// ArrayTermType r_vars = r_term->CreateArrayFromList();
3021// if (r_vars.empty()) {
3022// // Delete vars
3023// NL_PARSER(r_term, "NOT implemented!");
3024// // m_latter = getNoneObj();
3025//
3026// } else if (r_vars.size() == 1) {
3027//
3028// m_latter = Run(r_vars[0], this);
3029// for (auto &elem : l_vars) {
3030// if (elem->getTermID() == TermID::ELLIPSIS) {
3031// NL_PARSER(elem, "Ellipses unexpected!");
3032// } else if (elem->isNone()) {
3033// NL_PARSER(elem, "None var unexpected!");
3034// } else if (elem->m_right) {
3035//
3036// if (elem->m_right->m_id == TermID::INDEX) {
3037// SetIndexValue(elem, m_latter, this);
3038// } else if (elem->m_right->m_id == TermID::FIELD) {
3039// SetFieldValue(elem, m_latter, this);
3040// } else {
3041// NL_PARSER(elem, "Eval type '%s' not implemented!", toString(elem->m_right->m_id));
3042// }
3043//
3044// } else {
3045// elem->m_obj = m_latter;
3046// }
3047// }
3048//
3049// } else {
3050// // Что присваиваем (правая часть выражения)
3051// // @todo В будущем можно будет сделать сахар для обмена значениями при одинаковом кол-ве объектов у оператора присваивания
3052// // a, b = b, a; a, b, c = c, b, a; и т.д.
3053//
3054// if (l_vars.size() != r_vars.size()) {
3055// NL_PARSER(r_term, "Fail count right values! Expected one or %d.", (int) l_vars.size());
3056// }
3057// for (size_t i = 0; i < l_vars.size(); i++) {
3058// if (l_vars[i]->getTermID() == TermID::ELLIPSIS) {
3059// NL_PARSER(l_vars[i], "Ellipses unexpected!");
3060// } else if (l_vars[i]->isNone()) {
3061// NL_PARSER(l_vars[i], "None var unexpected!");
3062// } else {
3063//
3064// m_latter = Run(r_vars[i], this);
3065// l_vars[i]->m_obj = m_latter;
3066// }
3067// }
3068// }
3069// }
3070//
3071// return m_latter;
3072//
3073//
3074//
3075//}
3076//
3077//ObjPtr JIT::SetIndexValue(TermPtr &term, ObjPtr &value, Context * runner) {
3078//
3079// ASSERT(term->m_right);
3080//
3081// TermPtr index = term->m_right;
3082// ASSERT(index->size());
3083//
3084// switch (term->m_id) {
3085// case TermID::DICT:
3086// case TermID::STRCHAR:
3087// case TermID::STRWIDE:
3088// if (index->size() > 1) {
3089// NL_PARSER(index, "Strings and dictionaries do not support multiple dimensions!");
3090// }
3091// case TermID::TENSOR:
3092// break;
3093//
3094// case TermID::NAME:
3095// case TermID::LOCAL:
3096// case TermID::TYPE:
3097// case TermID::ARGS:
3098// case TermID::ARGUMENT:
3099// case TermID::STATIC:
3100// break;
3101//
3102// default:
3103// NL_PARSER(term, "Term type '%s' not indexable!", toString(term->m_id));
3104// }
3105//
3106// ObjPtr obj = CheckObjTerm_(term, runner, false);
3107// ASSERT(obj);
3108// ObjPtr ind = CheckObjTerm_(index->at(0).second, runner);
3109// ASSERT(ind);
3110//
3111// if (isStringChar(obj->getType())) {
3112//
3113// if (canCast(value->getType(), ObjType::Int8)) {
3114// obj->index_set_({ind->GetValueAsInteger()}, value);
3115// } else {
3116// NL_PARSER(term, "Fail cast from '%s' to ':Int8'", toString(value->getType()));
3117// }
3118// return value;
3119//
3120// } else if (isStringWide(obj->getType())) {
3121//
3122// if (canCast(value->getType(), m_rt->m_wide_char_type)) {
3123// obj->index_set_({ind->GetValueAsInteger()}, value);
3124// } else {
3125// NL_PARSER(term, "Fail cast from '%s' to '%s'", toString(value->getType()), newlang::toString(m_rt->m_wide_char_type));
3126// }
3127// return value;
3128// }
3129// NL_PARSER(term, "Index type '%s' not implemented!", toString(obj->getType()));
3130//}
3131//
3132//ObjPtr JIT::GetIndexValue(TermPtr &term, ObjPtr &obj, Context * runner) {
3133// ASSERT(term->m_right);
3134//
3135// TermPtr index = term->m_right;
3136// ASSERT(index->size());
3137//
3138// switch (term->m_id) {
3139// case TermID::DICT:
3140// case TermID::STRCHAR:
3141// case TermID::STRWIDE:
3142// if (index->size() > 1) {
3143// NL_PARSER(index, "Strings and dictionaries do not support multiple dimensions!");
3144// }
3145// case TermID::TENSOR:
3146// break;
3147//
3148// case TermID::NAME:
3149// case TermID::LOCAL:
3150// case TermID::TYPE:
3151// case TermID::ARGS:
3152// case TermID::ARGUMENT:
3153// case TermID::STATIC:
3154// break;
3155//
3156// default:
3157// NL_PARSER(term, "Term type '%s' not indexable!", toString(term->m_id));
3158// }
3159//
3160// ObjPtr ind = CheckObjTerm_(index->at(0).second, runner);
3161// ASSERT(ind);
3162//
3163// if (isStringChar(obj->getType())) {
3164// return obj->index_get({ind->GetValueAsInteger()});
3165// }
3166//
3167// NL_PARSER(term, "Index type '%s' not implemented!", toString(obj->getType()));
3168//}
3169//
3170//ObjPtr JIT::GetFieldValue(TermPtr &term, ObjPtr &value, Context * runner) {
3171// NL_PARSER(term, "GetFieldValue not implemented!");
3172//}
3173//
3174//ObjPtr JIT::SetFieldValue(TermPtr &term, ObjPtr &value, Context * runner) {
3175// NL_PARSER(term, "SetFieldValue not implemented!");
3176//}
static std::string MakeInclude(const TermPtr &ast)
bool Analyze(TermPtr term, NameLookupStack *stack_ptr=nullptr)
static LatterType Execute(Module &module, TermPtr ast, Context *runner)
Definition context.cpp:697
static std::string ExtractStaticVars(const TermPtr &ast, const std::string_view module)
Definition jit.cpp:913
static std::string ReplaceObjectInEmbedSource(const std::string_view embed, std::vector< std::string > &include, const TermPtr args=nullptr)
Definition jit.cpp:792
std::string MakeCodeFunction(const TermPtr &term)
Definition jit.cpp:917
static std::string MakeCommentPlace(const TermPtr &term)
Definition jit.cpp:695
static std::string MakeMain(const std::vector< std::string > &include)
Definition jit.cpp:749
bool LinkObjToExec(const std::string_view filename, std::vector< std::string > objs, std::vector< std::string > opts={})
Definition jit.cpp:624
std::vector< std::string > m_includes
Definition jit.h:260
JIT(const StringArray &args={})
Definition jit.cpp:2656
std::string MakeCodeModule(const TermPtr &term, std::string_view name, bool is_main)
Definition jit.cpp:822
clang::IntrusiveRefCntPtr< clang::DiagnosticIDs > pDiagIDs
Definition jit.h:110
void MakeFunctionRecursive_(const TermPtr &term, std::string &output, const std::string_view module)
Definition jit.cpp:929
ObjPtr Run(const std::string_view str, Obj *args=nullptr)
Definition jit.cpp:2558
static bool LLVMInitializeJIT()
Definition jit.h:191
std::vector< ModulePtr > m_module
Definition jit.h:96
clang::IntrusiveRefCntPtr< clang::DiagnosticOptions > DiagOpts
Definition jit.h:108
clang::TextDiagnosticPrinter * textDiagPrinter
Definition jit.h:109
static JIT * m_instance
Definition jit.h:129
Context & GetCtx()
Definition jit.h:103
MacroPtr m_macro
Definition jit.h:93
static std::string RegExpInlineComment(const std::string_view src)
Definition jit.cpp:704
std::unique_ptr< llvm::Module > MakeLLVMModule(std::string_view source, const std::vector< std::string > opts, std::string temp_dir="")
Definition jit.cpp:362
static std::string ExtractFunctionDecls(const TermPtr &ast, const std::string_view module)
Definition jit.cpp:665
std::vector< std::shared_ptr< Context > > m_ctx
Definition jit.h:97
ParserPtr GetParser()
Definition jit.cpp:2535
size_t m_repl_count
Definition jit.h:94
ObjPtr RunFile(std::string file, Obj *args=nullptr)
Definition jit.cpp:2540
clang::DiagnosticsEngine * pDiagnosticsEngine
Definition jit.h:111
std::string MakeApplicationSource(const TermPtr &ast)
Definition jit.cpp:722
static std::string MakeFunctionPrototype(const TermPtr &func, const std::string_view module)
Definition jit.cpp:684
NameLookupStack m_stack
Definition jit.h:90
bool MakeObjFile(const std::string_view filename, llvm::Module &module, const std::vector< std::string > opts)
Definition jit.cpp:584
static std::string MakeMainEmbed(const std::string_view embed_source, const std::vector< std::string > &include)
Definition jit.cpp:755
static bool LLVMInitialize()
Definition jit.h:183
static TermPtr MainArgs()
Definition jit.cpp:711
std::string MakeFuncDeclarations_(const TermPtr &term)
Definition jit.cpp:921
std::string MakeCodeRepl(const std::string_view source, const std::string_view name)
Definition jit.cpp:868
static std::string MakeBodyFunction(const TermPtr &ast)
Definition jit.cpp:925
bool ModuleCreate(FileModule &data, const std::string_view source)
Definition jit.cpp:2638
bool CreateMacro(const std::string_view text)
Definition jit.cpp:2783
VariablePair & GetVariablePair(bool editable=false)
Definition context.h:69
static std::string GetStackTrace()
Definition jit.cpp:2789
static ObjPtr CreateString(const std::string_view str, Sync *sync=nullptr)
Definition object.h:1596
std::variant< std::monostate, int64_t, double, void *, bool *, int8_t *, int16_t *, int32_t *, int64_t *, float *, double *, NativeData, std::string, TermPtr, Iterator< Obj > > m_var
Definition object.h:1897
ObjType m_var_type_current
Текущий тип значения объекта
Definition object.h:1864
double GetValueAsNumber() const
Definition object.cpp:1558
ObjType getType()
Definition object.h:423
static std::enable_if< std::is_same< T, std::string >::value||std::is_same< T, constchar * >::value, ObjPtr >::type CreateValue(T value, Sync *sync=nullptr)
Definition object.h:1562
std::wstring m_string
Содержит строку широких символов
Definition object.h:1906
std::string m_value
Содержит байтовую строку или байтовый массив с данными для представления в нативном виде (Struct,...
Definition object.h:1905
int64_t GetValueAsInteger() const
Definition object.cpp:1454
static ObjPtr CreateNone(Sync *sync=nullptr)
Definition object.h:1510
static ObjPtr CreateType(ObjType type, ObjType fixed=ObjType::None, bool is_init=false, Sync *sync=nullptr)
Definition object.h:1376
static size_t ParseTerm(TermPtr &term, const BlockType &buffer, const size_t skip=0, bool pragma_enable=true)
Definition parser.cpp:895
static std::string GetCurrentTimeStamp(time_t ts=std::time(NULL))
Definition parser.cpp:661
DiagPtr m_diag
Definition runtime.h:402
static void * GetNativeAddress(void *handle, const std::string_view name)
Definition jit.cpp:2796
TermPtr m_main_ast
Definition runtime.h:404
bool m_assert_enable
Definition runtime.h:388
std::string m_temp_dir
Definition runtime.h:385
static bool ExpandFileName(std::string &filename)
Definition runtime.cpp:1318
static std::vector< std::string > SplitChar(std::string_view str, const std::string_view delimiter)
Definition runtime.h:434
static TermPtr Create(TermID id, const char *text, parser::token_type lex_type=parser::token_type::END, size_t len=std::string::npos, location *loc=nullptr, std::shared_ptr< std::string > source=nullptr)
Definition term.h:335
static TermPtr CreateName(std::string name, TermID id=TermID::NAME)
Definition term.cpp:44
static TermPtr CreateDict()
Definition term.cpp:33
ObjPtr GetValueAsObject() const
Definition variable.cpp:458
LLVMTypeRef toLLVMType(ObjType t, bool none_if_error)
Definition jit.cpp:2487
ObjPtr CreateFromGenericValue(ObjType type, LLVMGenericValueRef ref, LLVMTypeRef llvm_type)
Definition jit.cpp:2454
LLVMGenericValueRef GetGenericValueRef(Obj &obj, LLVMTypeRef type)
Definition jit.cpp:2433
#define ALLOW_CHAR
#define NEWLANG_NS
Definition jit.h:71
#define NEWLANG_INDENT_OP
Definition jit.h:69
#define NEWLANG_PREFIX
Definition jit.h:70
int result
Definition lexer.l:367
#define LOG_RUNTIME(format,...)
Definition logger.h:26
#define LOG_PARSER(format,...)
Definition logger.h:25
#define VERIFY(exp)
Definition logger.h:65
#define ASSERT(condition)
Definition logger.h:60
#define LOG_ERROR(...)
Definition logger.h:122
Definition nlc.h:59
bool isConstName(const std::string_view name)
Definition types.h:1148
bool isFloatingType(ObjType t)
Definition types.h:732
std::string MakeName(std::string name)
Definition types.h:1180
std::shared_ptr< Parser > ParserPtr
Definition types.h:245
bool isIntegralType(ObjType t, bool includeBool)
Definition types.h:725
std::string MangaledFuncCPP(const char *name, const char *space=nullptr)
Definition jit.cpp:188
std::shared_ptr< Term > TermPtr
Definition variable.h:33
std::shared_ptr< Obj > ObjPtr
Definition variable.h:28
std::vector< std::string > StringArray
Definition types.h:148
bool Tranliterate(const wchar_t c, std::wstring &str)
Definition jit.cpp:44
std::string MangaledFunc(const std::string name)
Definition jit.cpp:201
std::string MangleName(const char *name)
Definition jit.cpp:209
std::string ReadFile(const char *fileName)
Definition runtime.cpp:1952
ObjType
Definition types.h:524
T repeat(T str, const std::size_t n)
Definition types.h:116
std::string NormalizeName(const std::string_view name)
Definition types.h:1152
const char * toString(TermID type)
Definition term.h:126
#define SCOPE_LOCK_WRITE(THIS)
Definition runtime.h:183
std::string GetIndent(int64_t offset=0)
Definition jit.cpp:952
std::string include
Definition runtime.h:136
std::string bytecode
Definition runtime.h:138
std::string name
Definition runtime.h:135
std::string source
Definition runtime.h:137
#define NL_PARSER(term, format,...)
Definition types.h:310
#define VERSION_SOURCE_FULL_ID
Definition version.h:7