NewLang Project
Yet another programm language
Loading...
Searching...
No Matches
analysis.cpp
Go to the documentation of this file.
1//#include "pch.h"
2
3#include "analysis.h"
4
5#include "term.h"
6#include "runtime.h"
7#include "builtin.h"
8#include "system.h"
9
10using namespace newlang;
11
13 if (term && term->getTermID() == TermID::EMBED) {
14 return false;
15 } else if (term && term->getTermID() == TermID::BLOCK) {
16 for (int i = 0; i < (int) term->m_block.size(); i++) {
17 if (!CheckClearFunction(term->m_block[i])) {
18 return false;
19 }
20 }
21 } else if (term && term->m_right) {
22 TermPtr temp = term->m_right;
23 while (temp) {
24 if (term->getTermID() == TermID::EMBED) {
25 return false;
26 }
27 if (term->m_right) {
28 temp = term->m_right;
29 } else {
30
31 break;
32 }
33 }
34 }
35 return true;
36}
37
39 // if (!proto || !proto->getType() || proto->getType()->isNone()) {
40 // return true;
41 // }
42 // if (!canCast(value->getType(), proto->getType())) {
43 // NL_PARSER(value, "Fail cast value '%s' to type '%s'", newlang::toString(value->getType()),
44 // newlang::toString(proto->getType()));
45 // }
46 //
47 // ObjType limit_type = value->getTypeAsLimit();
48 // if (!canCast(limit_type, value->getType())) {
49 // // Строку с одним символом можно преобразовать в арифметичсекий тип
50 // if (!(isArithmeticType(value->getType()) && value->is_string_type() && value->size() == 1)) {
51 // NL_PARSER(value, "Limit value overflow!");
52 // }
53 // }
54 return true;
55}
56
58
59 ASSERT(proto); // Прототип функции с аргументами по умолчанию
60 ASSERT(args); // Реальные аргументы
61
62 return true;
63
64 // bool named = false;
65 size_t args_count = proto->size();
66 bool is_ellipsis = false;
67 if (args_count) {
68 if (proto->at(args_count - 1).first.compare("...") == 0) {
69 is_ellipsis = true;
70 args_count--;
71 }
72 }
73 bool is_system_arg = false;
74 for (int i = 0; i < args->size(); i++) {
75
76 if (isSystemName(args->name(i))) {
77 is_system_arg = true;
78 continue;
79 }
80
81 if (is_system_arg) {
82 NL_PARSER(args->at(i).second, "System arguments must be passed last!");
83 }
84
85 if (args->name(i).empty()) {
86 // if(check_valid && named) {
87 // LOG_RUNTIME("Position %d requires a named argument!", (int) i + 1);
88 // }
89 ObjType base_type = ObjType::Any;
90 if (i < args_count) {
91 ASSERT(proto->at(1).second->m_type);
92 //if (proto->at(1).second->m_type) {
93 base_type = RunTime::BaseTypeFromString(&m_rt, proto->at(i).second->m_type->m_text);
94 //}
95 }
96
97
98 if (i < args_count) {
99 ASSERT(proto->at(i).second);
100 CheckArgsType_(proto->at(i).second, args->at(i).second);
101 // if (proto->at(i).second && at(i).second->getType() != ObjType::None) {
102 // if (!canCast(args->at(i).second->getType(), proto->at(i).second->getType())) {
103 // LOG_RUNTIME("Fail cast value '%s' to type '%s'", newlang::toString(args->at(i).second->getType()),
104 // newlang::toString(proto->at(i).second->getType()));
105 // }
106 // }
107 // if (!at(i).second) {
108 // at(i).second = Obj::CreateNone();
109 // }
110 // if (m_prototype && i < m_prototype->size()) {
111 // at(i).second->m_is_reference = (*m_prototype)[i].second->isRef();
112 // ObjType limit_type = (*in)[i].second->getTypeAsLimit();
113 // if (!canCast(limit_type, base_type)) {
114 // // Строку с одним символом можно преобразовать в арифметичсекий тип
115 // if (!(isArithmeticType(base_type) && (*in)[i].second->is_string_type() && (*in)[i].second->size() == 1)) {
116 // LOG_RUNTIME("Fail cast value !!!!!!!!!!!!!!");
117 // // LOG_RUNTIME("Fail cast value %s%s to type %s",
118 // // (*in)[i].second->toString().c_str(),
119 // // newlang::toString((*in)[i].second->getType()),
120 // // (*m_prototype)[i].second->m_type->asTypeString.c_str());
121 // }
122 // }
123 // }
124 //
125 // LOG_DEBUG("%s", (*in)[i].second->toString().c_str());
126 //
127 // at(i).second->op_assign((*in)[i].second->toType(base_type));
128 } else {
129 if (!is_ellipsis && i >= args_count) {
130 NL_PARSER(args->at(i).second, "Positional args overflow!");
131 }
132 // push_back(in->at(i).second->toType(base_type), in->at(i).first);
133 }
134 } else {
135 // named = true;
136 // auto found = proto->find(args->name(i));
137 // if (found != proto->end()) {
138 //
139 // CheckArgsType_(proto->at(i).second, (*found).second);
140 //
141 // // if ((*found).second && (*found).second->getType() != (*in)[i].second->getType() && (*found).second->getType() != ObjType::None) {
142 // // LOG_RUNTIME("Different type arg '%s' and '%s'", (*found).second->toString().c_str(),
143 // // (*in)[i].second->toString().c_str());
144 // // }
145 // // //@todo Проверка ограничений размер данных при указаном типе
146 // // if (!(*found).second) {
147 // // (*found).second = Obj::CreateNone();
148 // // }
149 // // (*found).second->op_assign((*in)[i].second);
150 // } else {
151 // for (int pos = 0; pos < size(); pos++) {
152 // // if (!at(pos).first.empty() && at(pos).first.compare(in->at(i).first) == 0) {
153 // // at(pos).second->op_assign(in[i]);
154 // goto done;
155 // // }
156 // }
157 // if (!is_ellipsis) {
158 // NL_PARSER(args->at(i).second, "Named arg '%s' not found!", args->name(i).c_str());
159 // }
160 // // push_back(in->at(i));
161 //done:
162 // ;
163 // }
164 }
165 }
166 for (int i = 0; i < args_count; i++) {
167 // if (!at(i).second) {
168 // LOG_RUNTIME("Argument %d '%s' missed!", (int) i + 1, at(i).first.c_str());
169 // }
170 }
171}
172
174 ASSERT(op);
175 ASSERT(op->m_left);
176 ASSERT(op->m_right);
177
178 // if (op->m_left->m_type) {
179 // if (op->m_text[0] == '+' || op->m_text[0] == '-' || op->m_text[0] == '*') { // +, +=, -, -=, *, *=
180 // } else if (op->m_text.compare("/") == 0 || op->m_text.compare("/=") == 0) {
181 // } else {
182 // if (!(op->m_text.compare("//") == 0 || op->m_text.compare("//=") == 0
183 // || op->m_text.compare("%") == 0 || op->m_text.compare("%=") == 0)) {
184 // NL_MESSAGE(LOG_LEVEL_INFO, op, "Unknown operator '%s'!", op->m_text.c_str());
185 // return false;
186 // }
187 // }
188 // }
189
190 return true;
191}
192
194 if (term->m_id == TermID::RANGE) {
195 if (term->m_type) {
196 if (!canCast(term->at("start").second->m_type, term->m_type)) {
197 ASSERT(term->at("start").second->m_type);
198 NL_MESSAGE(LOG_LEVEL_INFO, term->at("start").second, "Fail cast type %s to %s.",
199 term->at("start").second->m_type->asTypeString().c_str(), term->m_type->asTypeString().c_str());
200 return nullptr;
201 }
202
203 if (!canCast(term->at("stop").second->m_type, term->m_type)) {
204 ASSERT(term->at("stop").second->m_type);
205 NL_MESSAGE(LOG_LEVEL_INFO, term->at("stop").second, "Fail cast type %s to %s.",
206 term->at("stop").second->m_type->asTypeString().c_str(), term->m_type->asTypeString().c_str());
207 return nullptr;
208 }
209
210 if (!canCast(term->at("step").second->m_type, term->m_type)) {
211 ASSERT(term->at("step").second->m_type);
212 NL_MESSAGE(LOG_LEVEL_INFO, term->at("step").second, "Fail cast type %s to %s.",
213 term->at("step").second->m_type->asTypeString().c_str(), term->m_type->asTypeString().c_str());
214 return nullptr;
215 }
216 return term->m_type;
217
218 } else {
219
221 TermPtr sum_type = getDefaultType(sum);
222
223 std::array<TermPtr, 3> all{
224 term->at("start").second->m_type,
225 term->at("stop").second->m_type,
226 term->at("step").second->m_type};
227
228 ObjType temp;
229 for (auto &elem : all) {
230 if (elem) {
231 ASSERT(!elem->m_text.empty());
232 temp = GetBaseTypeFromString(elem->m_text);
233 if (static_cast<int> (temp) > static_cast<int> (sum)) {
234 sum = temp;
235 sum_type = elem;
236 }
237 }
238 }
239
240 for (auto &elem : all) {
241 if (elem) {
242 if (!canCast(elem, sum_type)) {
243 NL_MESSAGE(LOG_LEVEL_INFO, elem, "Fail cast type %s to %s.",
244 elem->asTypeString().c_str(), sum_type->asTypeString().c_str());
245 return nullptr;
246 }
247 }
248 }
249 return sum_type;
250 }
251 }
252 NL_MESSAGE(LOG_LEVEL_INFO, term, "Summary type for '%s' not implemented!", toString(term->m_id));
253
254 return nullptr;
255}
256
258 ASSERT(term);
259
260 /*
261 * [cond] --> {expr};
262 * [cond] --> {expr}, [...] --> {else};
263 */
264
265 for (int64_t i = 0; i < static_cast<int64_t> (term->m_block.size()); i++) {
266
267 TermPtr cond = term->m_block[i]->m_left;
268 ASSERT(cond);
269 if (cond->getTermID() == TermID::ELLIPSIS) { // else
270 if (i + 1 != term->m_block.size()) {
271 NL_MESSAGE(LOG_LEVEL_INFO, cond, "The term 'else' should be the last term in the list of conditions!");
272 return false;
273 }
274 } else {
275 if (!RecursiveAnalyzer(cond, stack)) {
276 return false;
277 }
278 }
279 if (!RecursiveAnalyzer(term->m_block[i]->m_right, stack)) {
280 return false;
281 }
282 }
283 return true;
284}
285
287 ASSERT(term);
288 ASSERT(term->m_left);
289 ASSERT(term->m_right);
290
291 if (!RecursiveAnalyzer(term->m_left, stack)) {
292 return false;
293 }
294 if (!RecursiveAnalyzer(term->m_right, stack)) {
295 return false;
296 }
297
298 if (!term->m_block.empty()) {
299 // else
300 ASSERT(term->m_block.size() == 1);
301 if (!RecursiveAnalyzer(term->m_block[0], stack)) {
302 return false;
303 }
304 }
305 return true;
306}
307
309 ASSERT(term);
310 ASSERT(term->m_left);
311 ASSERT(term->m_right);
312 ASSERT(term->m_block.empty());
313
314 if (!RecursiveAnalyzer(term->m_left, stack)) {
315 return false;
316 }
317 if (!RecursiveAnalyzer(term->m_right, stack)) {
318 return false;
319 }
320 return true;
321}
322
324 NL_MESSAGE(LOG_LEVEL_INFO, term, "CheckMatching not implemented!");
325 return false;
326}
327
329 NL_MESSAGE(LOG_LEVEL_INFO, term, "CkeckWith not implemented!");
330 return false;
331}
332
334
335 for (auto &elem : *term) {
336 RecursiveAnalyzer(elem.second, stack);
337 }
338 if (!term->m_block.empty()) {
339 ASSERT(term->m_block.size() == 1);
340 RecursiveAnalyzer(term->m_block[0], stack);
341 }
342 return true;
343}
344
346 if (term->find("step") == term->end()) {
347 term->push_back(Term::Create(TermID::INTEGER, "1"), "step");
348 }
349 if (!RecursiveAnalyzer(term->at("start").second, stack)
350 || !RecursiveAnalyzer(term->at("stop").second, stack)
351 || !RecursiveAnalyzer(term->at("step").second, stack)) {
352 return false;
353 }
354 TermPtr type = CalcSummaryType(term, stack);
355
356 if (!type) {
357 return false;
358 }
359
360 if (!term->m_type) {
361 term->m_type = type;
362 } else {
363 if (!canCast(type, term->m_type)) {
364 NL_MESSAGE(LOG_LEVEL_INFO, type, "Fail cast type %s to %s.", type->asTypeString().c_str(), term->m_type->asTypeString().c_str());
365 return false;
366 }
367 }
368 term->at("start").second->m_type = type;
369 term->at("stop").second->m_type = type;
370 term->at("step").second->m_type = type;
371
372 return true;
373}
374
376
377 ASSERT(native->getTermID() == TermID::NATIVE);
378 if (!native->m_right || native->m_right->m_text.compare("...") != 0) {
379 NL_MESSAGE(LOG_LEVEL_INFO, native, "Native name definition is supported with ellipses only!");
380 return false;
381 }
382
383 if (!m_rt.m_import_native) {
384 NL_MESSAGE(LOG_LEVEL_INFO, native, "Used flag '--nlc-no-import-native' to disabled import any native objects!");
385 return false;
386 }
387
388 if (proto->isCall() != native->isCall()) {
389 // Нативная функция с частичным прототипом
390 TermPtr from;
391 TermPtr to;
392 if (native->isCall()) {
393 from = native;
394 to = proto;
395 } else {
396 ASSERT(proto->isCall());
397 from = proto;
398 to = native;
399 }
400 for (int i = 0; i < from->size(); i++) {
401 to->push_back((*from)[i]);
402 }
403 to->m_is_call = from->m_is_call;
404 to->m_type = from->m_type;
405
406 } else if (!proto->isCall() && !native->isCall()) {
407 // Нативная переменная
408 if (!native->m_type) {
409 native->m_type = proto->m_type;
410 }
411
412 } else if (proto->isCall() && native->isCall()) {
413 NL_MESSAGE(LOG_LEVEL_INFO, native, "Native name definition is supported with ellipses only!");
414 return false;
415 }
416
417 proto->m_name_or_class = native->m_text.substr(1).c_str();
418 // proto->m_obj = CreateNative(proto, nullptr, false, proto->m_name.c_str());
419
420 if (!m_rt.GetNativeAddress(nullptr, proto->m_name_or_class.c_str())) {
421 NL_MESSAGE(LOG_LEVEL_INFO, native, "Error getting address native '%s'!", proto->toString().c_str());
422
423 return false;
424 }
425
426 return true;
427}
428
430 ASSERT(term->getTermID() == TermID::ITERATOR);
431 ASSERT(term->m_left);
432
433 for (auto &elem : *term) {
434 RecursiveAnalyzer(elem.second, stack);
435 }
436 return RecursiveAnalyzer(term->m_left, stack);
437}
438
439bool AstAnalysis::CheckOpType(TermPtr &op, TermPtr &left, TermPtr const right) {
440 if (left && right) {
441 if (!right->m_type && !left->m_type) {
442 return true;
443 }
444 if (!left->m_type && right->m_type) {
445 left->m_type = right->m_type;
446 return true;
447 } else if (left->m_type && !right->m_type) {
448 // Mark dynamic type check cast ??????????????????????????????????
449 return true;
450 }
451 if (right->m_type && left->m_type) {
452 if (!canCast(typeFromString(right->m_type, &m_rt), typeFromString(left->m_type, &m_rt))) {
453 if (canCast(typeFromString(left->m_type, &m_rt), typeFromString(right->m_type, &m_rt)) && isDefaultType(left->m_type)) {
454 // UpCast default type
455 left->m_type = right->m_type;
456 } else {
457 // ObjType l_type = typeFromString(left->m_type, &m_rt);
458 // ObjType r_type = typeFromString(right->m_type, &m_rt);
459 // if (isString(l_type) && isIntegralType(r_type, true)) {
460 // if (op->m_text.compare("*") == 0) {
461 // // 'string' * 3
462 // return true;
463 // } else if (op->m_type) {
464 // // str[1] = 13;
465 // ObjType str_type = typeFromString(op->m_type, &m_rt);
466 // if (isStringChar(str_type) && canCast(r_type, ObjType::Int8)) {
467 // return true;
468 // } else if (isStringWide(str_type) && canCast(r_type, RunTime::m_wide_char_type)) {
469 // return true;
470 // }
471 // }
472 // }
473 NL_MESSAGE(LOG_LEVEL_INFO, right, "Fail cast type %s to %s.", right->m_type->asTypeString().c_str(), left->m_type->asTypeString().c_str());
474 return false;
475 }
476 }
477 return true;
478 }
479 LOG_TEST("Skip CheckType left '%s' and right '%s'", left->toString().c_str(), right->toString().c_str());
480 LOG_TEST("Skip CheckType %s and %s", toString(left->getTermID()), right->toString().c_str());
481
482 return false;
483 }
484 return false;
485}
486
488 return nullptr;
489}
490
492 return false;
493}
494
496 NL_MESSAGE(LOG_LEVEL_INFO, term, "CheckField not implemented!");
497 return nullptr;
498}
499
501
502 ASSERT(index->size());
503 switch (term->m_id) {
504 case TermID::DICT:
505 case TermID::STRCHAR:
506 case TermID::STRWIDE:
507 if (index->size() > 1) {
508 NL_MESSAGE(LOG_LEVEL_INFO, index, "Strings and dictionaries do not support multiple dimensions!");
509 }
510 case TermID::TENSOR:
511 break;
512
513 case TermID::NAME:
514 case TermID::LOCAL:
515 case TermID::TYPE:
516 case TermID::ARGS:
517 case TermID::ARGUMENT:
518 case TermID::STATIC:
519 break;
520
521 default:
522 NL_MESSAGE(LOG_LEVEL_INFO, term, "Term type '%s' not indexable!", toString(term->m_id));
523 }
524
525 if (term->isNamed()) {
526 TermPtr rvar = LookupName(term, stack);
527 if (!rvar) {
528 NL_MESSAGE(LOG_LEVEL_INFO, term, "Name '%s' not exist!", term->m_text.c_str());
529 return false;
530 }
531 term->m_normalized = rvar->m_normalized;
532
533 if (term->isCall()) {
534 if (!CheckCall(rvar, term, stack)) {
535 return false;
536 }
537 }
538 } else {
539 NL_MESSAGE(LOG_LEVEL_INFO, term->m_right, "Type rvalue '%s' not implemented!", toString(term->m_id));
540 return false;
541 }
542
543 for (size_t i = 0; i < index->size(); i++) {
544 if (!RecursiveAnalyzer(index->at(i).second, stack)) {
545 return false;
546 }
547 if (index->at(i).second && canCast(index->at(i).second, m_rt.m_integer_type)) {
548 continue;
549 } else if (index->at(i).second->m_type) {
550 NL_MESSAGE(LOG_LEVEL_INFO, index->at(i).second, "Index type '%s' not implemented!", index->at(i).second->m_type->m_text.c_str());
551 return false;
552 } else {
553 NL_MESSAGE(LOG_LEVEL_INFO, index->at(i).second, "Index not implemented!");
554 return false;
555 }
556 }
557
558 ObjType type = typeFromString(term->m_type, &m_rt);
559 if (isStringChar(type) && canCast(value, ObjType::Int8)) {
560 return true;
561 } else if (isStringWide(type) && canCast(value, m_rt.m_wide_char_type)) {
562 return true;
563 }
564 NL_MESSAGE(LOG_LEVEL_INFO, term, "Index type not checked!");
565 return true;
566}
567
569
570 ASSERT(op);
571 ASSERT(op->m_left);
572 ASSERT(op->m_right);
573
574 if (op->m_left->isCall()) {
575 // Создание функции
576 if (op->m_left->m_left) {
577 NL_MESSAGE(LOG_LEVEL_INFO, op->m_left->m_left, "Multiple function creation is not supported!");
578 return false;
579 }
580
581 if (!(op->m_right->isBlock() || op->m_right->m_id == TermID::NATIVE)) {
582 NL_MESSAGE(LOG_LEVEL_INFO, op->m_left->m_left, "Create type '%s' is not implemented!", toString(op->m_right->m_id));
583 return false;
584 }
585
586 TermPtr proto = op->m_left;
587
588 proto->m_id = TermID::FUNCTION;
589 proto->m_normalized = stack.MakeInternalName(proto->m_text, true);
590 proto->m_is_owner = true;
591
592 ScopePush block_func(stack, proto, true);
593
594 if (!stack.AddName(proto)) {
595 return false;
596 }
597
598 ScopePush block_args(stack, proto, false);
599
600 // Add default args self and all args as dict
602 TermPtr arg;
603 std::string name;
604 for (size_t i = 0; i < proto->size(); i++) {
605
606 ASSERT(proto->at(i).second);
607 if (proto->at(i).second->getTermID() == TermID::ELLIPSIS) {
608 if (i + 1 != proto->size()) {
609 NL_MESSAGE(LOG_LEVEL_INFO, proto->at(i).second, "The ellipsis must be the last argument!");
610 return false;
611 }
612 break;
613 }
614
615 // Named arguments
616 if (proto->at(i).first.empty()) {
617 if (proto->at(i).second->getTermID() != TermID::NAME) {
618 NL_MESSAGE(LOG_LEVEL_INFO, proto->at(i).second, "Argument name expected!");
619 return false;
620 }
621 name = proto->at(i).second->m_text;
622 proto->at(i).first = name;
623 all->push_back({name, proto->at(i).second});
624
625 TermPtr none = Term::CreateNil();
626 none->m_normalized = NormalizeName(name);
627 if (!stack.AddName(none)) {
628 return false;
629 }
630 } else {
631 proto->at(i).second->m_normalized = NormalizeName(proto->at(i).first);
632 all->push_back({proto->at(i).first, proto->at(i).second});
633 if (!stack.AddName(proto->at(i).second)) {
634 return false;
635 }
636 }
637
638 name = "$";
639 name += std::to_string(i + 1);
640 // Positional arguments
641 if (!stack.AddName(proto->at(i).second, name.c_str())) {
642 return false;
643 }
644
645 if (isDefaultType(proto->at(i).second->m_type)) {
646 proto->at(i).second->m_type = getDefaultType(ObjType::Any);
647 }
648
649 }
650
651 // ScopePush block(stack, proto, &proto->m_int_vars, true);
652
653 TermPtr none = Term::CreateName("$0");
654 none->m_normalized = NormalizeName(none->m_text);
655
656 if (!stack.AddName(all, "$*") || !stack.AddName(none, "$0")) {
657 return false;
658 }
659
660
661 ASSERT(op->m_right);
662 if (op->m_right->getTermID() == TermID::NATIVE) {
663 return CheckNative_(proto, op->m_right); // && stack.FixTransaction();
664 } else {
665 return RecursiveAnalyzer(op->m_right, stack); // && stack.FixTransaction();
666 }
667
668 } else {
669
670 // Создание переменной
671 TermPtr term = op->m_left;
672
673 if (term->m_id == TermID::ELLIPSIS) {
674 if (op->getTermID() != TermID::ASSIGN) {
675 NL_MESSAGE(LOG_LEVEL_INFO, op, "To expand the search in a namespace, you must use the assignment operator!");
676 return false;
677 }
678 stack.SetLookupNamespace(op->m_right);
679 op->m_id = TermID::COMMENT; // op.reset(); Remove term for execution
680 return true;
681 }
682
683 TermPtr left_var;
684 std::string int_name;
685 bool name_exist;
686 while (term) {
687
688 left_var = LookupName(term, stack);
689 if (left_var) {
690 int_name = left_var->m_normalized;
691 } else {
692 int_name = stack.MakeInternalName(term->m_text, false);
693 left_var = LookupName(term, stack);
694 }
695
696 if (op->getTermID() == TermID::ASSIGN) {
697 if (!left_var) {
698 NL_MESSAGE(LOG_LEVEL_INFO, term, "Name '%s' not exist!", term->m_text.c_str());
699 return false;
700 }
701 } else if (op->isCreateNew()) {
702 if (!stack.empty() && stack.back().vars.find(int_name) != stack.back().vars.end()) {
703 NL_MESSAGE(LOG_LEVEL_INFO, term, "Local name '%s' already exist!", left_var->m_text.c_str());
704 return false;
705 }
706 }
707
708 if (!left_var) {
709 term->m_normalized = int_name;
710 if (!stack.AddName(term)) {
711 return false;
712 }
713 // left_var = term;
714 } else {
715 if (!term->m_type) {
716 term->m_type = left_var->m_type;
717 } else {
718 if (!canCast(left_var, term)) {
719 return false;
720 }
721 }
722 }
723
724
725 if (op->m_right->isNamed()) {
726 TermPtr r_var = LookupName(op->m_right, stack);
727 if (!r_var) {
728 NL_MESSAGE(LOG_LEVEL_INFO, op->m_right, "Name '%s' not exist!", op->m_right->m_text.c_str());
729 return false;
730 }
731 op->m_right->m_normalized = r_var->m_normalized;
732
733 if (op->m_right->isCall()) {
734 if (!CheckCall(r_var, op->m_right, stack)) {
735 return false;
736 }
737 }
738
739 } else if (op->m_right->getTermID() == TermID::NATIVE) {
740 if (!CheckNative_(term, op->m_right)) {
741 return false;
742 }
743 } else if (op->m_right->getTermID() == TermID::ELLIPSIS) {
744 if (!op->m_right->m_right) {
745 NL_MESSAGE(LOG_LEVEL_INFO, op->m_right, "Object expansion not found!");
746 return false;
747 }
748 if (!RecursiveAnalyzer(op->m_right->m_right, stack)) { // && CheckOpType(op, term, op->m_right->m_right)
749 return false;
750 }
751
752 } else {
753 if (!RecursiveAnalyzer(op->m_right, stack) && CheckOpType(op, term, op->m_right)) {
754 return false;
755 }
756 }
757
758
759 if (term->m_right) {
760 if (term->m_right->m_id == TermID::INDEX) {
761 return CheckIndex_(term, term->m_right, op->m_right, stack);
762 } else if (term->m_right->m_id == TermID::FIELD) {
763
764 term = CheckField_(term, term->m_right, stack);
765 if (!term) {
766 return false;
767 }
768
769 } else {
770 NL_MESSAGE(LOG_LEVEL_INFO, term, "Analysis type '%s' not implemented!", toString(term->m_right->m_id));
771 return false;
772 }
773 }
774
775
776 if (!term->m_type && op->m_right->m_type) {
777 term->m_type = op->m_right->m_type;
778 } else if (term->m_type && op->m_right->m_type) {
779 if (!canCast(op->m_right, term)) {
780 if (canCast(term, op->m_right) && isDefaultType(term->m_type)) {
781 // UpCast default type
782 term->m_type = op->m_right->m_type;
783 left_var->m_type = op->m_right->m_type; // // UpCast default type for variable
784 } else {
785 NL_MESSAGE(LOG_LEVEL_INFO, term, "Fail upcast type %s to %s!", term->m_type->toString().c_str(), op->m_right->m_type->toString().c_str());
786 return false;
787 }
788 }
789 } else if (term->m_type && !op->m_right->m_type) {
790 op->m_right->m_type = term->m_type;
791 }
792
793 if (!CheckAssignRef(term, op->m_right, stack)) {
794 return false;
795 }
796
797 term = term->m_left;
798 }
799 }
800 return true;
801}
802
804 ASSERT(left);
805 ASSERT(right);
806 TermPtr l_found = LookupName(left, stack);
807 TermPtr r_found = LookupName(right, stack);
808
809 if (right->isLiteral()) {
810 if (left->m_ref || (l_found && (l_found->m_ref && !left->m_is_take))) {
811 NL_MESSAGE(LOG_LEVEL_INFO, left, "You can't assign a literal to a reference variable!");
812 return CheckError(false);
813 }
814
815 left->m_is_owner = true; // owner := any literal
816 } else if (right->isNamed()) {
817 if (right->m_ref) {
818 if (left->m_is_owner || (l_found && l_found->m_is_owner)) {
819 NL_MESSAGE(LOG_LEVEL_INFO, left, "The variable is not a reference!");
820 return CheckError(false);
821 }
822 // left->m_is_reference = true;
823 left->m_ref = right->m_ref;
824 left->m_is_const = isConstRef(RefTypeFromString(right->m_ref->m_text));
825 if (l_found) {
826 // l_found->m_is_reference = true;
827 l_found->m_ref = right->m_ref;
828 }
829 } else {
830 if (!left->m_is_take) {
831 if (l_found && l_found->m_ref) {
832 NL_MESSAGE(LOG_LEVEL_INFO, left, "Required access operator by reference '*'!");
833 return CheckError(false);
834 } else if (r_found && !right->m_is_take) {
835 if (left->m_level <= r_found->m_level && !isReservedName(right->m_text)) {
836 NL_MESSAGE(LOG_LEVEL_INFO, left, "You can assign owner to a lower level variable only!");
837 return CheckError(false);
838 }
839 left->m_is_owner = true;
840 }
841 }
842 }
843 }
844
845 if (left->m_is_take) {
846 if (left->m_is_const || (l_found && l_found->m_is_const)) {
847 NL_MESSAGE(LOG_LEVEL_INFO, left, "You can assign a value to an immutable variable or reference!");
848 return CheckError(false);
849 }
850
851 if (l_found && l_found->m_ref && isLiteSyncRef(RefTypeFromString(l_found->m_ref->m_text))) {
852 NL_MESSAGE(LOG_LEVEL_INFO, left, "For assign value to a lite reference, you need to use operator with!");
853 return CheckError(false);
854 }
855
856 if (!right->m_is_take && r_found && r_found->m_is_owner) {
857 // Auto take // *ref := owner -> *ref := *owner
858 right->m_is_take = true;
859 }
860 }
861
862
863 if (right->m_ref) {
864 if (right->isLiteral()) {
865 NL_MESSAGE(LOG_LEVEL_INFO, right, "You can't get a reference to a literal!");
866 return CheckError(false);
867 }
868 ASSERT(r_found);
869 return CheckReference(r_found, right->m_ref);
870 }
871 return true;
872}
873
874bool AstAnalysis::CheckReference(TermPtr &term, const TermPtr & test_ref) {
875 ASSERT(term);
876 if (!term->m_ref) {
877 NL_MESSAGE(LOG_LEVEL_INFO, test_ref, "Object does not allow reference create!");
878 return CheckError(false);
879 }
880 if (!isValidReference(RefTypeFromString(term->m_ref->m_text), RefTypeFromString(test_ref->m_text))) {
881 NL_MESSAGE(LOG_LEVEL_INFO, test_ref, "The reference created is not allowed for type '%s'!", term->m_ref->m_text.c_str());
882 return CheckError(false);
883 }
884 if (!isValidReference(RefTypeFromString(term->m_ref->m_text), RefTypeFromString(test_ref->m_text))) {
885 NL_MESSAGE(LOG_LEVEL_INFO, test_ref, "The reference created is not allowed for type '%s'!", term->m_ref->m_text.c_str());
886 return CheckError(false);
887 }
888 return true;
889}
890
892
893 ASSERT(proto);
894 ASSERT(call);
895 ASSERT(call->isCall());
896
897 if (proto->isString() && proto->GetType()) {
898 if (proto->GetType()->m_text.compare(":FmtChar") == 0 || proto->GetType()->m_text.compare(":FmtWide") == 0) {
899 return CheckStrPrintf(proto->m_text, call, 0);
900 } else {
901 try {
902 MakeFormat(proto->m_text, call, &m_rt);
903 } catch (std::exception &ex) {
904 NL_MESSAGE(LOG_LEVEL_INFO, call, "%s", ex.what());
905 return false;
906 }
907 return true;
908 }
909 }
910
911 bool ell_count = false;
912 for (int i = 0; call->m_dims && i < call->m_dims->size(); i++) {
913 if (call->m_dims->at(i).second->m_id == TermID::ELLIPSIS) {
914 if (ell_count) {
915 NL_MESSAGE(LOG_LEVEL_INFO, call->m_dims->at(i).second, "Only one dimension of any size is possible!");
916 CheckError(false);
917 }
918 ell_count = true;
919 } else if (call->m_dims->at(i).second->isNone()) {
920 // Skip dim
921 } else {
922 RecursiveAnalyzer(call->m_dims->at(i).second, stack);
923 if (!(canCast(call->m_dims->at(i).second, ObjType::Integer) || canCast(call->m_dims->at(i).second, ObjType::Range))) {
924 NL_MESSAGE(LOG_LEVEL_INFO, call->m_dims->at(i).second, "Unsupported type for tensor dimension!");
925 CheckError(false);
926 }
927 }
928 }
929
930 if (proto->isCall()) {
931 // Check function args and calc default values
932 bool is_system_args = false;
933 bool is_named_args = false;
934 bool is_ellipsys = proto->is_variable_args();
935 int max_args = proto->size() - is_ellipsys;
936 int pos = 0;
937 for (; pos < max_args; pos++) {
938
939 std::string_view proto_arg_name = proto->at(pos).first;
940 TermPtr proto_default_value;
941
942 if (proto->at(pos).second->m_name_or_class.empty()) {
943 proto_default_value = nullptr;
944 } else {
945 proto_default_value = proto->at(pos).second;
946 }
947
948
949 if (pos < call->size()) {
950
951
952 if (!CheckCallArg(call, pos, stack)) {
953 return false;
954 }
955
956 // Системые аргументы могут быть только самыми последними в списке
957 if (isSystemName(proto_arg_name)) {
958 is_system_args = true;
959 } else {
960 if (is_system_args) {
961 NL_MESSAGE(LOG_LEVEL_INFO, proto->at(pos).second, "System argument name expected!");
962 return false;
963 }
964 }
965
966 TermPtr value = call->at(pos).second;
967
968 if (!RecursiveAnalyzer(value, stack)) {
969 NL_MESSAGE(LOG_LEVEL_INFO, proto->at(pos).second, "System argument name expected!");
970 return false;
971 }
972
973 if (value->isNamed()) {
974
975 ObjType value_type = typeFromString(value->m_type, &m_rt);
976
977 if (value->m_right) {
978
979 if (value->m_right->m_id == TermID::INDEX) {
980 if (isString(value_type) || isDictionary(value_type)) {
981
982 if (value->m_right->size() != 1) {
983 NL_MESSAGE(LOG_LEVEL_INFO, value->m_right, "Strings and dictionaries support single dimensions only!");
984 return false;
985 }
986
987 if (isStringChar(value_type)) {
988 value_type = ObjType::Int8;
989 } else if (isStringWide(value_type)) {
990 value_type = m_rt.m_wide_char_type;
991 }
992
993 } else if (value_type == ObjType::Any) {
994 // Skip - not check
995 } else {
996 NL_MESSAGE(LOG_LEVEL_INFO, value->m_right, "Index for type '%s' not implemented!", toString(value_type));
997 return false;
998 }
999
1000 } else if (value->m_right->m_id == TermID::FIELD) {
1001 NL_MESSAGE(LOG_LEVEL_INFO, proto->at(pos).second, "System argument name expected!");
1002 return false;
1003 } else {
1004 NL_MESSAGE(LOG_LEVEL_INFO, proto->at(pos).second, "Index type '%s' not implemented!", toString(value->m_right->m_id));
1005 return false;
1006 }
1007 }
1008
1009 if (value_type != ObjType::Any && !canCast(value_type, typeFromString(proto->at(pos).second->m_type, &m_rt))) {
1010 ASSERT(proto->at(pos).second->GetType());
1011 NL_MESSAGE(LOG_LEVEL_INFO, proto->at(pos).second, "Fail cast from '%s' to '%s'!",
1012 toString(value_type), proto->at(pos).second->GetType()->m_text.c_str());
1013 return false;
1014 }
1015
1016
1017 if (proto->at(pos).second->GetType()) {
1018 if (proto->at(pos).second->GetType()->m_text.compare(":FmtChar") == 0 || proto->at(pos).second->GetType()->m_text.compare(":FmtWide") == 0) {
1019 if (!CheckStrPrintf(value->m_text, call, pos + 1)) {
1020 return false;
1021 }
1022 }
1023 }
1024 }
1025
1026 // Именованные аргументы идут после обычных
1027 if (!call->at(pos).first.empty()) {
1028 is_named_args = true;
1029
1030 if (proto->find(call->at(pos).first) == proto->end()) {
1031 NL_MESSAGE(LOG_LEVEL_INFO, call->at(pos).second, "Named argument '%s' not found in prototype '%s'!", call->at(pos).first.c_str(), proto->m_text.c_str());
1032 return false;
1033 }
1034
1035 } else {
1036 if (is_named_args) {
1037 NL_MESSAGE(LOG_LEVEL_INFO, proto->at(pos).second, "Expecting a named argument!");
1038 return false;
1039 }
1040 }
1041
1042 } else {
1043 // Заполняются значения по умолчанию
1044 if (!proto_default_value) {
1045 NL_MESSAGE(LOG_LEVEL_INFO, proto->at(pos).second, "The argument '%s' has no default value!", proto_arg_name.begin());
1046 return false;
1047 } else {
1048 call->push_back(proto_default_value, proto_arg_name.begin());
1049 }
1050 }
1051 }
1052
1053 if (pos < call->size()) {
1054 if (!is_ellipsys) {
1055 NL_MESSAGE(LOG_LEVEL_INFO, proto->at(pos).second, "An unexpected extra argument!");
1056 return false;
1057 }
1058 while (pos < call->size()) {
1059 if (!RecursiveAnalyzer(call->at(pos).second, stack)) {
1060 return false;
1061 }
1062 pos++;
1063 }
1064 } else if (pos > call->size()) {
1065
1066 NL_MESSAGE(LOG_LEVEL_INFO, proto->at(pos).second, "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
1067 return false;
1068
1069 }
1070
1071 } else {
1072
1073 for (int i = 0; i < call->size(); i++) {
1074 if (!CheckCallArg(call, i, stack)) {
1075 return false;
1076 }
1077 }
1078 }
1079
1080 // Object clone
1081 if (!proto->isCall() && !isTypeName(proto->m_normalized)) {
1082 ObjType proto_type = typeFromString(proto->m_type, &m_rt);
1083 if (isString(proto_type)) {
1084 if (proto_type == ObjType::FmtChar || proto_type == ObjType::FmtWide) {
1085 //todo // NL_MESSAGE(LOG_LEVEL_INFO, call->at(0).second, "Argument type checking for printf is not implemented!");
1086 // return CheckStrPrintf(??????????????????????????, call, 0);
1087 } else {
1088 return CheckStrFormat(proto->m_text, call, &m_rt);
1089 }
1090 } else if (call->size()) {
1091 NL_MESSAGE(LOG_LEVEL_INFO, call->at(0).second, "Cloning objects with field overrides is not implemented!");
1092 return false;
1093 }
1094 }
1095
1096 return true;
1097}
1098
1099void AstAnalysis::CheckDims(TermPtr &dims, NameLookupStack & stack, bool allow_none, bool allow_ellipsis) {
1100 bool is_ellipsis = false;
1101 for (int index = 0; dims && index < dims->size(); index++) {
1102 if (dims->at(index).second->isNone()) {
1103 // Skip None
1104 if (!allow_none) {
1105 NL_MESSAGE(LOG_LEVEL_INFO, dims->at(index).second, "Empty dimension is not allowed!");
1106 CheckError(false);
1107 }
1108
1109 } else if (dims->at(index).second->m_id == TermID::ELLIPSIS) {
1110 if (!allow_ellipsis) {
1111 NL_MESSAGE(LOG_LEVEL_INFO, dims->at(index).second, "Unlimited dimension is not allowed!");
1112 CheckError(false);
1113 }
1114 if (is_ellipsis) {
1115 NL_MESSAGE(LOG_LEVEL_INFO, dims->at(index).second, "Only one dimension of unlimited is possible!");
1116 CheckError(false);
1117 }
1118 is_ellipsis = true;
1119 } else {
1120 if (!RecursiveAnalyzer(dims->at(index).second, stack)) {
1121 CheckError(false);
1122 }
1123 }
1124 }
1125}
1126
1127bool AstAnalysis::CheckCallArg(TermPtr &call, size_t arg_pos, NameLookupStack & stack) {
1128 ASSERT(call);
1129 ASSERT(arg_pos < call->size());
1130
1131 TermPtr arg = call->at(arg_pos).second;
1132 ASSERT(arg);
1133
1134 if (arg->m_id == TermID::FILLING) {
1135
1136 // Заполнение значений вызовом функции
1137 // :Tensor[10](1, 2, 3, ... rand() ... );
1138
1139 ASSERT(!arg->m_left);
1140 ASSERT(arg->m_right);
1141
1142 TermPtr fill_obj = arg->m_right;
1143 ASSERT(fill_obj);
1144
1145 if (fill_obj->m_text.find("rndа") != std::string::npos) {
1146 ASSERT(1);
1147 }
1148 LOG_DEBUG("%s", fill_obj->m_text.c_str());
1149
1150 if (!RecursiveAnalyzer(fill_obj, stack)) {
1151 return false;
1152 }
1153
1154 if (arg_pos + 1 != call->size()) {
1155 NL_MESSAGE(LOG_LEVEL_INFO, fill_obj, "Filling is supported for the last argument only!");
1156 return false;
1157 }
1158
1159 if (!call->m_dims || !call->m_dims->size()) {
1160 NL_MESSAGE(LOG_LEVEL_INFO, call, "Object has no dimensions!");
1161 return false;
1162 }
1163
1164 CheckDims(call->m_dims, stack, false, false);
1165
1166 if (fill_obj->size()) {
1167 NL_MESSAGE(LOG_LEVEL_INFO, fill_obj, "Argument in function for filling not implemented!");
1168 return false;
1169 }
1170
1171 if (fill_obj->m_type) {
1172 if (call->m_type) {
1173 if (!canCast(fill_obj, call)) {
1174 NL_MESSAGE(LOG_LEVEL_INFO, fill_obj, "Fail cast type '%s' to '%s' type!", fill_obj->m_type->m_text.c_str(), call->m_type->m_text.c_str());
1175 return false;
1176 }
1177 } else {
1178 call->m_type = fill_obj->m_type;
1179 }
1180 }
1181
1182 return true;
1183
1184 } else if (arg->m_id == TermID::ELLIPSIS) {
1185
1186 if (!arg->m_name_or_class.empty()) {
1187 NL_MESSAGE(LOG_LEVEL_INFO, arg, "Named ellipsys not implemented!");
1188 return false;
1189 }
1190
1191 TermPtr fill_obj = arg->m_right;
1192
1193 if (!fill_obj) {
1194 // Fill with last values to full size
1195 return true;
1196 }
1197
1198 // if (!fill_obj->m_type) {
1199 // fill_obj->m_type = getDefaultType(ObjType::Dictionary);
1200 // } else {
1201 // if (!canCast(fill_obj->m_type, ObjType::Dictionary)) {
1202 // NL_MESSAGE(LOG_LEVEL_INFO, fill_obj, "Fail cast type '%s' to dictionary type!", fill_obj->m_type->m_text.c_str());
1203 // return false;
1204 // }
1205 // }
1206
1207 return RecursiveAnalyzer(fill_obj, stack);
1208
1209 } else if (arg->m_id == TermID::RANGE) {
1210
1211 if (!RecursiveAnalyzer(arg, stack)) {
1212 return false;
1213 }
1214
1215 if (!arg->m_name_or_class.empty()) {
1216 NL_MESSAGE(LOG_LEVEL_INFO, arg, "Named range not implemented!");
1217 return false;
1218 }
1219
1220 if (arg->m_type) {
1221 if (call->m_type) {
1222 if (!canCast(arg, call)) {
1223 NL_MESSAGE(LOG_LEVEL_INFO, arg, "Fail cast type '%s' to '%s' type!",
1224 arg->m_type->m_text.c_str(), call->m_type->m_text.c_str());
1225 return false;
1226 }
1227 } else {
1228 call->m_type = arg->m_type;
1229 }
1230 }
1231 return true;
1232
1233 } else {
1234
1235 // if (!arg->m_is_const) {
1236 // if (!arg->m_ref && !arg->m_is_reference) {
1237 // NL_MESSAGE(LOG_LEVEL_INFO, arg, "The mutable argument can be a reference only!");
1238 // return false;
1239 // } else {
1240 // RefType ref_type = RefTypeFromString(arg->m_ref->m_text);
1241 // if (isConstRef(ref_type)) {
1242 // NL_MESSAGE(LOG_LEVEL_INFO, arg, "The mutable argument can be a mutable reference only!");
1243 // return false;
1244 // }
1245 // }
1246 // }
1247 return RecursiveAnalyzer(arg, stack);
1248 }
1249}
1250
1251fmt::dynamic_format_arg_store<fmt::format_context> AstAnalysis::MakeFormatArgs(TermPtr args, RunTime * rt) {
1252
1253 fmt::dynamic_format_arg_store<fmt::format_context> store;
1254
1255 for (int i = 0; i < args->size(); i++) {
1256
1257 ObjType type = typeFromString(args->at(i).second->m_type, rt);
1258
1259 switch (type) {
1260 case ObjType::Bool:
1261 case ObjType::Int8:
1262 case ObjType::Byte:
1263 case ObjType::Char:
1264 case ObjType::Int16:
1265 case ObjType::Word:
1266 case ObjType::Int32:
1267 case ObjType::DWord:
1268 case ObjType::Int64:
1269 case ObjType::DWord64:
1270 store.push_back(parseInteger(args->at(i).second->m_text.c_str()));
1271 break;
1272
1273 case ObjType::Float16:
1274 case ObjType::Float32:
1275 case ObjType::Single:
1276 case ObjType::Float64:
1277 case ObjType::Double:
1278 store.push_back(parseDouble(args->at(i).second->m_text.c_str()));
1279 break;
1280
1281 default:
1282 store.push_back(args->at(i).second->toString());
1283 break;
1284 // LOG_RUNTIME("Support type '%s' not implemented!", toString(type));
1285 }
1286 }
1287 return store;
1288}
1289
1290std::string AstAnalysis::MakeFormat(const std::string_view format, TermPtr args, RunTime * rt) {
1291 ASSERT(args);
1292 std::string result;
1293 std::string conv_format;
1294 try {
1295 conv_format = ConvertToVFormat_(format, *args);
1296 fmt::dynamic_format_arg_store<fmt::format_context> store = MakeFormatArgs(args, rt);
1297 result = fmt::vformat(conv_format, store);
1298 } catch (const std::exception& ex) {
1299 LOG_TEST("Fail format from '%s' to '%s'", format.begin(), conv_format.c_str());
1300 LOG_RUNTIME("%s", ex.what());
1301 }
1302 return result;
1303}
1304
1305bool AstAnalysis::CheckStrFormat(const std::string_view format, TermPtr args, RunTime * rt) {
1306 ASSERT(args);
1307 std::string conv_format;
1308 try {
1309 conv_format = ConvertToVFormat_(format, *args);
1310 fmt::dynamic_format_arg_store<fmt::format_context> store = MakeFormatArgs(args, rt);
1311 fmt::vformat(conv_format, store);
1312 } catch (const std::exception& ex) {
1313 NL_MESSAGE(LOG_LEVEL_INFO, args, "Fail format %s (from '%s' to '%s')", ex.what(), format.begin(), conv_format.c_str());
1314 return false;
1315 }
1316 return true;
1317}
1318
1319bool AstAnalysis::CheckStrPrintf(const std::string_view format, TermPtr args, int start) {
1320
1321 static const std::string flags_list = "-+0123456789.lLh"; // '#', '*'
1322 static const std::string types_list = "diufFeEgGxXaAoscp"; //, 'n'
1323
1324 static std::string valid_chars;
1325 if (valid_chars.empty()) {
1326 valid_chars.append(flags_list);
1327 valid_chars.append(types_list);
1328 }
1329
1330 bool result = true;
1331 int aind = start;
1332
1333 size_t pos = 0;
1334 while (pos < format.length()) {
1335 pos = format.find('%', pos);
1336 if (pos == format.npos) {
1337 break;
1338 }
1339 pos++;
1340 if (format[pos] == '%' || !format[pos]) {
1341 pos++;
1342 continue;
1343 }
1344
1345 if (aind >= args->size()) {
1346
1347 NL_MESSAGE(LOG_LEVEL_INFO, args, "Argument number '%d' is missing!", (int) pos);
1348 return false;
1349
1350 } else {
1351
1352 if (isSystemName((*args)[aind].first)) {
1353 NL_MESSAGE(LOG_LEVEL_INFO, (*args)[aind].second, "System argument name not allowed!");
1354 return false;
1355 }
1356
1357 if (!(*args)[aind].first.empty()) {
1358 NL_MESSAGE(LOG_LEVEL_INFO, (*args)[aind].second, "Named argument '%s' not allowed!", (*args)[aind].first.c_str());
1359 return false;
1360 }
1361
1362 pos = format.find_first_not_of(valid_chars, pos);
1363 if (pos == format.npos) {
1364 pos = format.length();
1365 }
1366 pos--;
1367
1368 TermPtr test_type;
1369 ObjType cast = ObjType::None;
1370 switch (format[pos]) {
1371
1372 case 'a': //%a Шестнадцатеричное в виде 0xh.hhhhp+d (только С99)
1373 case 'A': //%A Шестнадцатеричное в виде 0Xh.hhhhP+d (только С99)
1374 case 'd': //%d Десятичное целое со знаком
1375 case 'i': //%i Десятичное целое со знаком
1376 case 'o': //%o Восьмеричное без знака
1377 case 'u': //%u Десятичное целое без знака
1378 case 'x': //%x Шестнадцатеричное без знака (буквы на нижнем регистре)
1379 case 'X': //%X Шестнадцатеричное без знака (буквы на верхнем регистре)
1380 cast = ObjType::Int32;
1381 if (pos && (format[pos - 1] == 'l' || format[pos - 1] == 'L')) {
1382 cast = ObjType::Int64;
1383 } else if (pos && format[pos - 1] == 'h') {
1384 cast = ObjType::Int16;
1385 }
1386
1387 // if ((*args)[aind].second->getType() == ObjType::Iterator) {
1388 // ASSERT((*args)[aind].second->m_iterator);
1389 // test_type = (*args)[aind].second->m_iterator->data().second->getType();
1390 // } else {
1391 test_type = (*args)[aind].second;
1392 // }
1393
1394 if (!canCast(test_type, cast)) {
1395 ASSERT(test_type->m_type);
1396 NL_MESSAGE(LOG_LEVEL_INFO, (*args)[aind].second, "Fail cast from '%s' to '%s'!", test_type->m_type->m_text.c_str(), newlang::toString(cast));
1397 result = false;
1398 }
1399 break;
1400
1401
1402 case 'e'://%e Экспоненциальное представление ('е' на нижнем регистре)
1403 case 'E'://%E Экспоненциальное представление ('Е' на верхнем регистре)
1404 case 'f'://%f Десятичное с плавающей точкой
1405 case 'g'://%g В зависимости от того, какой вывод будет короче, используется %е или %f
1406 case 'G'://%G В зависимости от того, какой вывод будет короче, используется %Е или %F
1407
1408 cast = ObjType::Float64;
1409 if (!canCast((*args)[aind].second, cast)) {
1410 ASSERT((*args)[aind].second->m_type);
1411 NL_MESSAGE(LOG_LEVEL_INFO, (*args)[aind].second, "Fail cast from '%s' to '%s'!", (*args)[aind].second->m_type->m_text.c_str(), newlang::toString(cast));
1412 result = false;
1413 }
1414 break;
1415
1416 case 'c':
1417 cast = ObjType::Int8;
1418 if (pos && (format[pos - 1] == 'l' || format[pos - 1] == 'L')) {
1419 cast = ObjType::Int32;
1420 }
1421 if (!canCast((*args)[aind].second, cast)) {
1422 ASSERT((*args)[aind].second->m_type);
1423 NL_MESSAGE(LOG_LEVEL_INFO, (*args)[aind].second, "Fail cast from '%s' to '%s'!", (*args)[aind].second->m_type->m_text.c_str(), newlang::toString(cast));
1424 result = false;
1425 }
1426 break;
1427
1428 case 's':
1429 cast = ObjType::StrChar;
1430 if (pos && (format[pos - 1] == 'l' || format[pos - 1] == 'L')) {
1431 cast = ObjType::StrWide;
1432 }
1433 if (!canCast((*args)[aind].second, cast)) {
1434 ASSERT((*args)[aind].second->m_type);
1435 NL_MESSAGE(LOG_LEVEL_INFO, (*args)[aind].second, "Fail cast from '%s' to '%s'!", (*args)[aind].second->m_type->m_text.c_str(), newlang::toString(cast));
1436 result = false;
1437 }
1438 break;
1439
1440
1441 case 'p':
1442 cast = ObjType::Pointer;
1443 if (!canCast((*args)[aind].second, cast)) {
1444 ASSERT((*args)[aind].second->m_type);
1445 NL_MESSAGE(LOG_LEVEL_INFO, (*args)[aind].second, "Fail cast from '%s' to '%s'!", (*args)[aind].second->m_type->m_text.c_str(), newlang::toString(cast));
1446 result = false;
1447 }
1448 break;
1449
1450 default:
1451 NL_MESSAGE(LOG_LEVEL_INFO, args, "Format modifier '%c' at pos %d in '%s' not supported!", format[pos], (int) pos, format.begin());
1452 result = false;
1453 }
1454 }
1455 pos++;
1456 aind++; // Следующий аргумент
1457 }
1458
1459 if (aind < args->size()) {
1460 NL_MESSAGE(LOG_LEVEL_INFO, (*args)[aind].second, "Extra arguments more %d!", aind);
1461
1462 return false;
1463 }
1464
1465 return result;
1466}
1467
1468/*
1469 *
1470 *
1471 *
1472 */
1474 if (!result) {
1477
1478 LOG_PARSER("fatal error: too many errors emitted %d, stopping now [-nlc-error-limit=]", m_diag->m_error_count);
1479 }
1480 }
1481 return result;
1482}
1483
1485 BlockType block{term};
1486 return Analyze(block, stack_ptr);
1487}
1488
1490
1491 m_diag->m_error_count = 0;
1492
1493 StorageTerm::ModuleMapType temp_external;
1494 NameLookupStack temp_stack(m_rt, temp_external);
1495
1496 if (!stack_ptr) {
1497 stack_ptr = &temp_stack;
1498 }
1499
1500 try {
1501
1502 for (auto &elem : block) {
1503 RecursiveAnalyzer(elem, *stack_ptr);
1504 }
1505
1506 if (m_diag->m_error_count) {
1507 LOG_PARSER("fatal error: %d generated. ", m_diag->m_error_count);
1508 }
1509 } catch (ParserError err) {
1510 return false;
1511 }
1512 return !m_diag->m_error_count;
1513}
1514
1516 if (isReservedName(term->m_text)) {
1517 term->m_normalized = term->m_text;
1518 return term;
1519 }
1520
1521 TermPtr result = stack.LookupName(term->m_text);
1522 if (!result) {
1523 VariablePair * found = m_rt.FindObject(term->m_text);
1524 if (found) {
1525 result = found->term;
1526 if(!result){
1527 NL_MESSAGE(LOG_LEVEL_INFO, term, "Forward '%s' not exist! %s", term->m_text.c_str(), m_rt.Dump(term->m_text).c_str());
1528 }
1529 }
1530 }
1531
1532 if (result) {
1533 ASSERT(!result->m_normalized.empty());
1534 term->m_normalized = result->m_normalized;
1535 if (!CheckOpType(term, result, term)) {
1536
1537 return nullptr;
1538 }
1539 }
1540 return result;
1541}
1542
1544 TermPtr found;
1545
1546 switch (term->getTermID()) {
1547 case TermID::SEQUENCE:
1548 { // Top-level objects are not deleted after processing is complete
1549 for (auto &elem : term->m_block) {
1550 // LOG_TEST("%d: %s", step++, elem->m_text.c_str());
1551 // Возможные ошибки подсчитываются внутри RecursiveAnalyzer
1552 RecursiveAnalyzer(elem, stack);
1553 }
1554 return true;
1555 }
1556 case TermID::BLOCK:
1557 case TermID::BLOCK_PLUS:
1559 case TermID::BLOCK_TRY:
1560 {
1561 // int step = 1;
1562 // LOG_TEST("Block '%s'", term->m_namespace ? term->m_namespace->m_text.c_str() : "");
1563
1564 ScopePush block_scope(stack, term->m_namespace);
1565 for (auto &elem : term->m_block) {
1566 // LOG_TEST("%d: %s", step++, elem->m_text.c_str());
1567 // Возможные ошибки подсчитываются внутри RecursiveAnalyzer
1568 RecursiveAnalyzer(elem, stack);
1569 }
1570 return true;
1571 }
1572
1573 case TermID::MODULE:
1574 if (!m_rt.m_import_module) {
1575 NL_MESSAGE(LOG_LEVEL_INFO, term, "Used flag '--nlc-no-import-module' to disabled import any modules!");
1576 return false;
1577 }
1578
1579 case TermID::NAME:
1580 case TermID::TYPE:
1581 case TermID::ARGS:
1582 case TermID::ARGUMENT:
1583 case TermID::LOCAL:
1584 case TermID::STATIC:
1585 case TermID::NAMESPACE:
1586 {
1587 found = LookupName(term, stack);
1588 if (CheckError(!!found)) {
1589
1590 ASSERT(!found->m_normalized.empty());
1591 term->m_normalized = found->m_normalized;
1592
1593 } else {
1594 NL_MESSAGE(LOG_LEVEL_INFO, term, "NameLookup fail for '%s'! %s", term->m_text.c_str(), stack.Dump().c_str());
1595 return false;
1596 }
1597
1598 if (term->isCall()) {
1599 return CheckError(CheckCall(found, term, stack));
1600 }
1601 return true;
1602 }
1603
1604 case TermID::OP_MATH:
1605 return CheckError(
1606 RecursiveAnalyzer(term->m_left, stack)
1607 && RecursiveAnalyzer(term->m_right, stack)
1608 && CheckOpType(term, term->m_left, term->m_right)
1609 && UpcastOpType(term));
1610
1611 case TermID::OP_COMPARE:
1612 return CheckError(
1613 RecursiveAnalyzer(term->m_left, stack)
1614 && RecursiveAnalyzer(term->m_right, stack));
1615
1616 case TermID::INT_PLUS:
1617 case TermID::INT_MINUS:
1618 case TermID::INT_REPEAT:
1619 {
1620 if (term->m_right && !RecursiveAnalyzer(term->m_right, stack)) {
1621 return false;
1622 }
1623 if (term->m_namespace) {
1624 return CheckError(stack.LookupBlock_(term->m_namespace));
1625 }
1626 return true;
1627 }
1628
1629 case TermID::EVAL:
1630 {
1631 if (!m_rt.m_eval_enable) {
1632 NL_MESSAGE(LOG_LEVEL_INFO, term, "Used flag '--nlc-no-eval-enable' to disabled the eval statement!");
1633 return false;
1634 }
1635 return true;
1636 }
1637
1638 case TermID::ASSIGN:
1639 case TermID::CREATE_NEW:
1640 case TermID::CREATE_USE:
1641 case TermID::PURE_NEW:
1642 case TermID::PURE_USE:
1643 return CheckError(CreateOp_(term, stack));
1644
1645 case TermID::INTEGER:
1646 case TermID::NUMBER:
1647 case TermID::RATIONAL:
1648 case TermID::END:
1649 return true;
1650
1651 case TermID::DICT:
1652 case TermID::TENSOR:
1653 case TermID::STRWIDE:
1654 case TermID::STRCHAR:
1655 return CheckError(CheckItems_(term, stack));
1656
1657 case TermID::FOLLOW:
1658 return CheckError(CheckFollow_(term, stack));
1659 case TermID::MATCHING:
1660 return CheckError(CheckMatching_(term, stack));
1661 case TermID::WHILE:
1662 return CheckError(CheckWhile_(term, stack));
1663 case TermID::DOWHILE:
1664 return CheckError(CheckDoWhile_(term, stack));
1665 case TermID::RANGE:
1666 return CheckError(CkeckRange_(term, stack));
1667 case TermID::WITH:
1668 return CheckError(CheckWith_(term, stack));
1669 case TermID::TAKE:
1670 return CheckError(CheckTake_(term, stack));
1671 case TermID::ITERATOR:
1672 return CheckError(Iterator_(term, stack));
1673
1674
1675 case TermID::EMBED:
1676 if (!m_rt.m_embed_source) {
1677 NL_MESSAGE(LOG_LEVEL_INFO, term, "Use flag '--nlc-embed-source' to enable embedded source code!");
1678 return false;
1679 }
1680 return false; // Not implemented
1681
1682 default:
1683 NL_MESSAGE(LOG_LEVEL_INFO, term, "AstRecursiveAnalyzer for type '%s' not implemented!", toString(term->getTermID()));
1684 }
1685 return false;
1686}
1687
1689 for (int i = 0; i < term->size(); i++) {
1690 RecursiveAnalyzer(term->at(i).second, stack);
1691 }
1692 return true;
1693}
1694
1695std::string AstAnalysis::MakeInclude(const TermPtr & ast) {
1696 std::string result;
1697 if (ast->isExport()) {
1698 if (ast->m_id == TermID::MACRO_DEL || ast->m_left->m_id == TermID::MACRO_SEQ) {
1699 result += ast->toString(true);
1700 result += ";\n";
1701 } else {
1702 ASSERT(ast->isCreate());
1703 TermPtr term = ast->m_left;
1704 while (term) {
1705 if (Term::isExportName(term)) {
1706 result += term->m_text;
1707 result += " ";
1708 result += ast->m_text;
1709 result += " ...;\n";
1710 }
1711 term = term->m_left;
1712 }
1713 }
1714 } else if (ast->m_right) {
1715 result += MakeInclude(ast->m_right);
1716 }
1717 for (auto &elem : ast->m_block) {
1718 result += MakeInclude(elem);
1719 }
1720 return result;
1721}
bool CheckClearFunction(TermPtr term)
Definition analysis.cpp:12
bool CheckCall(TermPtr &proto, TermPtr &call, NameLookupStack &stack)
Definition analysis.cpp:891
bool UpcastOpType(TermPtr &op)
Definition analysis.cpp:173
bool CheckAssignRef(TermPtr &left, TermPtr &right, NameLookupStack &stack)
Definition analysis.cpp:803
bool CheckMatching_(TermPtr &term, NameLookupStack &stack)
Definition analysis.cpp:323
bool RecursiveAnalyzer(TermPtr term, NameLookupStack &stack)
static bool CheckStrPrintf(const std::string_view format, TermPtr args, int start)
bool CheckArgs_(TermPtr proto, TermPtr args)
Definition analysis.cpp:57
bool CheckItems_(TermPtr &term, NameLookupStack &stack)
static std::string ConvertToVFormat_(const std::string_view format, T &args)
Definition analysis.h:115
bool CheckReference(TermPtr &term, const TermPtr &test_ref)
Definition analysis.cpp:874
static std::string MakeInclude(const TermPtr &ast)
TermPtr LookupName(TermPtr &term, NameLookupStack &stack)
TermPtr CheckGetValue_(TermPtr &obj, NameLookupStack &stack)
Definition analysis.cpp:487
bool CheckDoWhile_(TermPtr &term, NameLookupStack &stack)
Definition analysis.cpp:308
bool CreateOp_(TermPtr &term, NameLookupStack &stack)
Definition analysis.cpp:568
bool CheckNative_(TermPtr &term)
bool CheckCallArg(TermPtr &call, size_t arg_pos, NameLookupStack &stack)
TermPtr CalcSummaryType(const TermPtr &term, NameLookupStack &stack)
Definition analysis.cpp:193
bool Analyze(TermPtr term, NameLookupStack *stack_ptr=nullptr)
bool CheckWith_(TermPtr &term, NameLookupStack &stack)
Definition analysis.cpp:328
void CheckDims(TermPtr &dims, NameLookupStack &stack, bool allow_none, bool allow_ellipsis)
bool CheckArgsType_(TermPtr proto, TermPtr value)
Definition analysis.cpp:38
bool CheckIndex_(TermPtr &term, TermPtr &index, TermPtr &value, NameLookupStack &stack)
Definition analysis.cpp:500
bool CheckSetValue_(TermPtr &obj, TermPtr &value, NameLookupStack &stack)
Definition analysis.cpp:491
bool CheckError(bool result)
bool CkeckRange_(TermPtr &term, NameLookupStack &stack)
Definition analysis.cpp:345
bool CheckWhile_(TermPtr &term, NameLookupStack &stack)
Definition analysis.cpp:286
bool CheckTake_(TermPtr &term, NameLookupStack &stack)
Definition analysis.cpp:333
bool CheckFollow_(TermPtr &term, NameLookupStack &stack)
Definition analysis.cpp:257
static fmt::dynamic_format_arg_store< fmt::format_context > MakeFormatArgs(TermPtr args, RunTime *rt)
TermPtr CheckField_(TermPtr &term, TermPtr &field, NameLookupStack &stack)
Definition analysis.cpp:495
static std::string MakeFormat(const std::string_view format, TermPtr args, RunTime *rt)
bool CheckOpType(TermPtr &op, TermPtr &left, const TermPtr right)
Definition analysis.cpp:439
static bool CheckStrFormat(const std::string_view format, TermPtr args, RunTime *rt)
bool Iterator_(TermPtr &term, NameLookupStack &stack)
Definition analysis.cpp:429
int m_error_limit
Definition diag.h:195
int m_error_count
Definition diag.h:196
std::string Dump(const std::string_view filter="", const char delim=';')
Definition types.cpp:314
VariablePair * FindObject(const std::string_view name)
Definition types.cpp:287
std::string Dump()
Definition term.cpp:691
bool LookupBlock_(TermPtr &term)
Definition term.cpp:647
std::string MakeInternalName(const TermPtr &term, bool is_static)
Definition term.cpp:309
void SetLookupNamespace(TermPtr ns)
Definition term.cpp:200
TermPtr LookupName(std::string name)
Definition term.cpp:541
bool AddName(const TermPtr var, const char *alt_name=nullptr)
Definition term.cpp:426
bool m_embed_source
Definition runtime.h:390
static ObjType BaseTypeFromString(RunTime *rt, const std::string_view text, bool *has_error=nullptr)
Definition runtime.cpp:1525
bool m_import_native
Definition runtime.h:392
static ObjType m_integer_type
Definition runtime.h:291
static void * GetNativeAddress(void *handle, const std::string_view name)
Definition jit.cpp:2796
static ObjType m_wide_char_type
Definition runtime.h:289
bool m_import_module
Definition runtime.h:391
std::map< std::string, StorageTerm > ModuleMapType
Definition term.h:172
static bool isExportName(const TermPtr &term)
Definition term.h:565
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 CreateNil()
Definition term.cpp:28
static TermPtr CreateName(std::string name, TermID id=TermID::NAME)
Definition term.cpp:44
static TermPtr CreateDict()
Definition term.cpp:33
int result
Definition lexer.l:367
#define LOG_RUNTIME(format,...)
Definition logger.h:26
#define LOG_LEVEL_INFO
Definition logger.h:87
#define LOG_PARSER(format,...)
Definition logger.h:25
#define LOG_DEBUG(...)
Definition logger.h:119
#define LOG_TEST(...)
Definition logger.h:36
#define ASSERT(condition)
Definition logger.h:60
Definition nlc.h:59
bool isStringChar(ObjType t)
Definition types.h:759
bool isTypeName(ObjType t)
Definition types.h:804
const TermPtr getDefaultType(const std::string_view text)
Definition parser.cpp:1072
bool isStringWide(ObjType t)
Definition types.h:764
bool isString(ObjType t)
Definition types.h:769
constexpr bool isValidReference(RefType type, RefType test)
Definition variable.h:102
bool isDictionary(ObjType t)
Definition types.h:784
std::shared_ptr< Term > TermPtr
Definition variable.h:33
int64_t parseInteger(const char *str)
Definition types.h:998
bool isSystemName(const std::string_view name)
Definition types.h:1118
double parseDouble(const char *str)
Definition types.h:1012
constexpr RefType RefTypeFromString(const std::string_view text)
Definition variable.h:55
bool isReservedName(const std::string_view name)
Definition types.h:1036
std::vector< TermPtr > BlockType
Definition types.h:239
ObjType GetBaseTypeFromString(const std::string_view type_arg, bool *has_error=nullptr)
Definition parser.cpp:1102
ObjType typeFromString(TermPtr &term, RunTime *rt, bool *has_error)
Definition runtime.cpp:2243
ObjType
Definition types.h:524
std::string NormalizeName(const std::string_view name)
Definition types.h:1152
const char * toString(TermID type)
Definition term.h:126
constexpr bool isLiteSyncRef(RefType type)
Definition variable.h:86
bool isDefaultType(const TermPtr &term)
Definition parser.cpp:1060
constexpr bool isConstRef(RefType type)
Definition variable.h:94
bool canCast(const ObjType from, const ObjType to)
Definition types.h:967
#define NL_PARSER(term, format,...)
Definition types.h:310
#define NL_MESSAGE(level, term, format,...)
Definition types.h:318