13 if (term && term->getTermID() == TermID::EMBED) {
15 }
else if (term && term->getTermID() == TermID::BLOCK) {
16 for (
int i = 0; i < (int) term->m_block.size(); i++) {
21 }
else if (term && term->m_right) {
24 if (term->getTermID() == TermID::EMBED) {
65 size_t args_count = proto->size();
66 bool is_ellipsis =
false;
68 if (proto->at(args_count - 1).first.compare(
"...") == 0) {
73 bool is_system_arg =
false;
74 for (
int i = 0; i < args->size(); i++) {
82 NL_PARSER(args->at(i).second,
"System arguments must be passed last!");
85 if (args->name(i).empty()) {
91 ASSERT(proto->at(1).second->m_type);
99 ASSERT(proto->at(i).second);
129 if (!is_ellipsis && i >= args_count) {
130 NL_PARSER(args->at(i).second,
"Positional args overflow!");
166 for (
int i = 0; i < args_count; i++) {
196 if (!
canCast(term->at(
"start").second->m_type, term->m_type)) {
197 ASSERT(term->at(
"start").second->m_type);
199 term->at(
"start").second->m_type->asTypeString().c_str(), term->m_type->asTypeString().c_str());
203 if (!
canCast(term->at(
"stop").second->m_type, term->m_type)) {
204 ASSERT(term->at(
"stop").second->m_type);
206 term->at(
"stop").second->m_type->asTypeString().c_str(), term->m_type->asTypeString().c_str());
210 if (!
canCast(term->at(
"step").second->m_type, term->m_type)) {
211 ASSERT(term->at(
"step").second->m_type);
213 term->at(
"step").second->m_type->asTypeString().c_str(), term->m_type->asTypeString().c_str());
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};
229 for (
auto &elem : all) {
231 ASSERT(!elem->m_text.empty());
233 if (
static_cast<int> (temp) >
static_cast<int> (sum)) {
240 for (
auto &elem : all) {
242 if (!
canCast(elem, sum_type)) {
244 elem->asTypeString().c_str(), sum_type->asTypeString().c_str());
265 for (int64_t i = 0; i < static_cast<int64_t> (term->m_block.size()); i++) {
267 TermPtr cond = term->m_block[i]->m_left;
270 if (i + 1 != term->m_block.size()) {
298 if (!term->m_block.empty()) {
300 ASSERT(term->m_block.size() == 1);
312 ASSERT(term->m_block.empty());
335 for (
auto &elem : *term) {
338 if (!term->m_block.empty()) {
339 ASSERT(term->m_block.size() == 1);
346 if (term->find(
"step") == term->end()) {
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());
368 term->at(
"start").second->m_type = type;
369 term->at(
"stop").second->m_type = type;
370 term->at(
"step").second->m_type = type;
378 if (!native->m_right || native->m_right->m_text.compare(
"...") != 0) {
388 if (proto->isCall() != native->isCall()) {
392 if (native->isCall()) {
400 for (
int i = 0; i < from->size(); i++) {
401 to->push_back((*from)[i]);
403 to->m_is_call = from->m_is_call;
404 to->m_type = from->m_type;
406 }
else if (!proto->isCall() && !native->isCall()) {
408 if (!native->m_type) {
409 native->m_type = proto->m_type;
412 }
else if (proto->isCall() && native->isCall()) {
417 proto->m_name_or_class = native->m_text.substr(1).c_str();
433 for (
auto &elem : *term) {
441 if (!right->m_type && !left->m_type) {
444 if (!left->m_type && right->m_type) {
445 left->m_type = right->m_type;
447 }
else if (left->m_type && !right->m_type) {
451 if (right->m_type && left->m_type) {
455 left->m_type = right->m_type;
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());
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());
503 switch (term->m_id) {
507 if (index->size() > 1) {
525 if (term->isNamed()) {
531 term->m_normalized = rvar->m_normalized;
533 if (term->isCall()) {
543 for (
size_t i = 0; i < index->size(); i++) {
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());
574 if (op->m_left->isCall()) {
576 if (op->m_left->m_left) {
581 if (!(op->m_right->isBlock() || op->m_right->m_id ==
TermID::NATIVE)) {
590 proto->m_is_owner =
true;
592 ScopePush block_func(stack, proto,
true);
598 ScopePush block_args(stack, proto,
false);
604 for (
size_t i = 0; i < proto->size(); i++) {
606 ASSERT(proto->at(i).second);
608 if (i + 1 != proto->size()) {
616 if (proto->at(i).first.empty()) {
621 name = proto->at(i).second->m_text;
622 proto->at(i).first = name;
623 all->push_back({name, proto->at(i).second});
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)) {
639 name += std::to_string(i + 1);
641 if (!stack.
AddName(proto->at(i).second, name.c_str())) {
684 std::string int_name;
690 int_name = left_var->m_normalized;
701 }
else if (op->isCreateNew()) {
702 if (!stack.empty() && stack.back().vars.find(int_name) != stack.back().vars.end()) {
709 term->m_normalized = int_name;
716 term->m_type = left_var->m_type;
718 if (!
canCast(left_var, term)) {
725 if (op->m_right->isNamed()) {
731 op->m_right->m_normalized = r_var->m_normalized;
733 if (op->m_right->isCall()) {
734 if (!
CheckCall(r_var, op->m_right, stack)) {
744 if (!op->m_right->m_right) {
761 return CheckIndex_(term, term->m_right, op->m_right, stack);
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)) {
782 term->m_type = op->m_right->m_type;
783 left_var->m_type = op->m_right->m_type;
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());
789 }
else if (term->m_type && !op->m_right->m_type) {
790 op->m_right->m_type = term->m_type;
809 if (right->isLiteral()) {
810 if (left->m_ref || (l_found && (l_found->m_ref && !left->m_is_take))) {
815 left->m_is_owner =
true;
816 }
else if (right->isNamed()) {
818 if (left->m_is_owner || (l_found && l_found->m_is_owner)) {
823 left->m_ref = right->m_ref;
827 l_found->m_ref = right->m_ref;
830 if (!left->m_is_take) {
831 if (l_found && l_found->m_ref) {
834 }
else if (r_found && !right->m_is_take) {
835 if (left->m_level <= r_found->m_level && !
isReservedName(right->m_text)) {
839 left->m_is_owner =
true;
845 if (left->m_is_take) {
846 if (left->m_is_const || (l_found && l_found->m_is_const)) {
856 if (!right->m_is_take && r_found && r_found->m_is_owner) {
858 right->m_is_take =
true;
864 if (right->isLiteral()) {
881 NL_MESSAGE(
LOG_LEVEL_INFO, test_ref,
"The reference created is not allowed for type '%s'!", term->m_ref->m_text.c_str());
885 NL_MESSAGE(
LOG_LEVEL_INFO, test_ref,
"The reference created is not allowed for type '%s'!", term->m_ref->m_text.c_str());
897 if (proto->isString() && proto->GetType()) {
898 if (proto->GetType()->m_text.compare(
":FmtChar") == 0 || proto->GetType()->m_text.compare(
":FmtWide") == 0) {
903 }
catch (std::exception &ex) {
911 bool ell_count =
false;
912 for (
int i = 0; call->m_dims && i < call->m_dims->size(); i++) {
919 }
else if (call->m_dims->at(i).second->isNone()) {
930 if (proto->isCall()) {
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;
937 for (; pos < max_args; pos++) {
939 std::string_view proto_arg_name = proto->at(pos).first;
942 if (proto->at(pos).second->m_name_or_class.empty()) {
943 proto_default_value =
nullptr;
945 proto_default_value = proto->at(pos).second;
949 if (pos < call->size()) {
958 is_system_args =
true;
960 if (is_system_args) {
966 TermPtr value = call->at(pos).second;
973 if (value->isNamed()) {
977 if (value->m_right) {
982 if (value->m_right->size() != 1) {
1010 ASSERT(proto->at(pos).second->GetType());
1012 toString(value_type), proto->at(pos).second->GetType()->m_text.c_str());
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) {
1027 if (!call->at(pos).first.empty()) {
1028 is_named_args =
true;
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());
1036 if (is_named_args) {
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());
1048 call->push_back(proto_default_value, proto_arg_name.begin());
1053 if (pos < call->size()) {
1058 while (pos < call->size()) {
1064 }
else if (pos > call->size()) {
1073 for (
int i = 0; i < call->size(); i++) {
1081 if (!proto->isCall() && !
isTypeName(proto->m_normalized)) {
1090 }
else if (call->size()) {
1100 bool is_ellipsis =
false;
1101 for (
int index = 0; dims && index < dims->size(); index++) {
1102 if (dims->at(index).second->isNone()) {
1110 if (!allow_ellipsis) {
1129 ASSERT(arg_pos < call->size());
1131 TermPtr arg = call->at(arg_pos).second;
1142 TermPtr fill_obj = arg->m_right;
1145 if (fill_obj->m_text.find(
"rndа") != std::string::npos) {
1148 LOG_DEBUG(
"%s", fill_obj->m_text.c_str());
1154 if (arg_pos + 1 != call->size()) {
1159 if (!call->m_dims || !call->m_dims->size()) {
1164 CheckDims(call->m_dims, stack,
false,
false);
1166 if (fill_obj->size()) {
1171 if (fill_obj->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());
1178 call->m_type = fill_obj->m_type;
1186 if (!arg->m_name_or_class.empty()) {
1191 TermPtr fill_obj = arg->m_right;
1215 if (!arg->m_name_or_class.empty()) {
1224 arg->m_type->m_text.c_str(), call->m_type->m_text.c_str());
1228 call->m_type = arg->m_type;
1253 fmt::dynamic_format_arg_store<fmt::format_context> store;
1255 for (
int i = 0; i < args->size(); i++) {
1270 store.push_back(
parseInteger(args->at(i).second->m_text.c_str()));
1278 store.push_back(
parseDouble(args->at(i).second->m_text.c_str()));
1282 store.push_back(args->at(i).second->toString());
1293 std::string conv_format;
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());
1307 std::string conv_format;
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());
1321 static const std::string flags_list =
"-+0123456789.lLh";
1322 static const std::string types_list =
"diufFeEgGxXaAoscp";
1324 static std::string valid_chars;
1325 if (valid_chars.empty()) {
1326 valid_chars.append(flags_list);
1327 valid_chars.append(types_list);
1334 while (pos < format.length()) {
1335 pos = format.find(
'%', pos);
1336 if (pos == format.npos) {
1340 if (format[pos] ==
'%' || !format[pos]) {
1345 if (aind >= args->size()) {
1357 if (!(*args)[aind].first.empty()) {
1362 pos = format.find_first_not_of(valid_chars, pos);
1363 if (pos == format.npos) {
1364 pos = format.length();
1370 switch (format[pos]) {
1381 if (pos && (format[pos - 1] ==
'l' || format[pos - 1] ==
'L')) {
1383 }
else if (pos && format[pos - 1] ==
'h') {
1391 test_type = (*args)[aind].second;
1394 if (!
canCast(test_type, cast)) {
1395 ASSERT(test_type->m_type);
1409 if (!
canCast((*args)[aind].second, cast)) {
1410 ASSERT((*args)[aind].second->m_type);
1418 if (pos && (format[pos - 1] ==
'l' || format[pos - 1] ==
'L')) {
1421 if (!
canCast((*args)[aind].second, cast)) {
1422 ASSERT((*args)[aind].second->m_type);
1430 if (pos && (format[pos - 1] ==
'l' || format[pos - 1] ==
'L')) {
1433 if (!
canCast((*args)[aind].second, cast)) {
1434 ASSERT((*args)[aind].second->m_type);
1443 if (!
canCast((*args)[aind].second, cast)) {
1444 ASSERT((*args)[aind].second->m_type);
1451 NL_MESSAGE(
LOG_LEVEL_INFO, args,
"Format modifier '%c' at pos %d in '%s' not supported!", format[pos], (
int) pos, format.begin());
1459 if (aind < args->size()) {
1486 return Analyze(block, stack_ptr);
1497 stack_ptr = &temp_stack;
1502 for (
auto &elem : block) {
1517 term->m_normalized = term->m_text;
1534 term->m_normalized =
result->m_normalized;
1546 switch (term->getTermID()) {
1549 for (
auto &elem : term->m_block) {
1564 ScopePush block_scope(stack, term->m_namespace);
1565 for (
auto &elem : term->m_block) {
1590 ASSERT(!found->m_normalized.empty());
1591 term->m_normalized = found->m_normalized;
1598 if (term->isCall()) {
1623 if (term->m_namespace) {
1689 for (
int i = 0; i < term->size(); i++) {
1697 if (ast->isExport()) {
1699 result += ast->toString(
true);
1711 term = term->m_left;
1714 }
else if (ast->m_right) {
1717 for (
auto &elem : ast->m_block) {
bool CheckClearFunction(TermPtr term)
bool CheckCall(TermPtr &proto, TermPtr &call, NameLookupStack &stack)
bool UpcastOpType(TermPtr &op)
bool CheckAssignRef(TermPtr &left, TermPtr &right, NameLookupStack &stack)
bool CheckMatching_(TermPtr &term, NameLookupStack &stack)
bool RecursiveAnalyzer(TermPtr term, NameLookupStack &stack)
static bool CheckStrPrintf(const std::string_view format, TermPtr args, int start)
bool CheckArgs_(TermPtr proto, TermPtr args)
bool CheckItems_(TermPtr &term, NameLookupStack &stack)
static std::string ConvertToVFormat_(const std::string_view format, T &args)
bool CheckReference(TermPtr &term, const TermPtr &test_ref)
static std::string MakeInclude(const TermPtr &ast)
TermPtr LookupName(TermPtr &term, NameLookupStack &stack)
TermPtr CheckGetValue_(TermPtr &obj, NameLookupStack &stack)
bool CheckDoWhile_(TermPtr &term, NameLookupStack &stack)
bool CreateOp_(TermPtr &term, NameLookupStack &stack)
bool CheckNative_(TermPtr &term)
bool CheckCallArg(TermPtr &call, size_t arg_pos, NameLookupStack &stack)
TermPtr CalcSummaryType(const TermPtr &term, NameLookupStack &stack)
bool Analyze(TermPtr term, NameLookupStack *stack_ptr=nullptr)
bool CheckWith_(TermPtr &term, NameLookupStack &stack)
void CheckDims(TermPtr &dims, NameLookupStack &stack, bool allow_none, bool allow_ellipsis)
bool CheckArgsType_(TermPtr proto, TermPtr value)
bool CheckIndex_(TermPtr &term, TermPtr &index, TermPtr &value, NameLookupStack &stack)
bool CheckSetValue_(TermPtr &obj, TermPtr &value, NameLookupStack &stack)
bool CheckError(bool result)
bool CkeckRange_(TermPtr &term, NameLookupStack &stack)
bool CheckWhile_(TermPtr &term, NameLookupStack &stack)
bool CheckTake_(TermPtr &term, NameLookupStack &stack)
bool CheckFollow_(TermPtr &term, NameLookupStack &stack)
static fmt::dynamic_format_arg_store< fmt::format_context > MakeFormatArgs(TermPtr args, RunTime *rt)
TermPtr CheckField_(TermPtr &term, TermPtr &field, NameLookupStack &stack)
static std::string MakeFormat(const std::string_view format, TermPtr args, RunTime *rt)
bool CheckOpType(TermPtr &op, TermPtr &left, const TermPtr right)
static bool CheckStrFormat(const std::string_view format, TermPtr args, RunTime *rt)
bool Iterator_(TermPtr &term, NameLookupStack &stack)
std::string Dump(const std::string_view filter="", const char delim=';')
VariablePair * FindObject(const std::string_view name)
bool LookupBlock_(TermPtr &term)
std::string MakeInternalName(const TermPtr &term, bool is_static)
void SetLookupNamespace(TermPtr ns)
TermPtr LookupName(std::string name)
bool AddName(const TermPtr var, const char *alt_name=nullptr)
static ObjType BaseTypeFromString(RunTime *rt, const std::string_view text, bool *has_error=nullptr)
static ObjType m_integer_type
static void * GetNativeAddress(void *handle, const std::string_view name)
static ObjType m_wide_char_type
std::map< std::string, StorageTerm > ModuleMapType
static bool isExportName(const TermPtr &term)
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)
static TermPtr CreateNil()
static TermPtr CreateName(std::string name, TermID id=TermID::NAME)
static TermPtr CreateDict()
#define LOG_RUNTIME(format,...)
#define LOG_PARSER(format,...)
#define ASSERT(condition)
bool isStringChar(ObjType t)
bool isTypeName(ObjType t)
const TermPtr getDefaultType(const std::string_view text)
bool isStringWide(ObjType t)
constexpr bool isValidReference(RefType type, RefType test)
bool isDictionary(ObjType t)
std::shared_ptr< Term > TermPtr
int64_t parseInteger(const char *str)
bool isSystemName(const std::string_view name)
double parseDouble(const char *str)
constexpr RefType RefTypeFromString(const std::string_view text)
bool isReservedName(const std::string_view name)
std::vector< TermPtr > BlockType
ObjType GetBaseTypeFromString(const std::string_view type_arg, bool *has_error=nullptr)
ObjType typeFromString(TermPtr &term, RunTime *rt, bool *has_error)
std::string NormalizeName(const std::string_view name)
const char * toString(TermID type)
constexpr bool isLiteSyncRef(RefType type)
bool isDefaultType(const TermPtr &term)
constexpr bool isConstRef(RefType type)
bool canCast(const ObjType from, const ObjType to)
#define NL_PARSER(term, format,...)
#define NL_MESSAGE(level, term, format,...)