// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details #include "Luau/Predicate.h" #include "Luau/Ast.h" namespace Luau { std::optional tryGetLValue(const AstExpr& node) { const AstExpr* expr = &node; while (auto e = expr->as()) expr = e->expr; if (auto local = expr->as()) return Symbol{local->local}; else if (auto global = expr->as()) return Symbol{global->name}; else if (auto indexname = expr->as()) { if (auto lvalue = tryGetLValue(*indexname->expr)) return Field{std::make_shared(*lvalue), indexname->index.value}; } else if (auto indexexpr = expr->as()) { if (auto lvalue = tryGetLValue(*indexexpr->expr)) if (auto string = indexexpr->index->as()) return Field{std::make_shared(*lvalue), std::string(string->value.data, string->value.size)}; } return std::nullopt; } std::pair> getFullName(const LValue& lvalue) { const LValue* current = &lvalue; std::vector keys; while (auto field = get(*current)) { keys.push_back(field->key); current = field->parent.get(); if (!current) LUAU_ASSERT(!"LValue root is a Field?"); } const Symbol* symbol = get(*current); return {*symbol, std::vector(keys.rbegin(), keys.rend())}; } std::string toString(const LValue& lvalue) { auto [symbol, keys] = getFullName(lvalue); std::string s = toString(symbol); for (std::string key : keys) s += "." + key; return s; } void merge(RefinementMap& l, const RefinementMap& r, std::function f) { auto itL = l.begin(); auto itR = r.begin(); while (itL != l.end() && itR != r.end()) { const auto& [k, a] = *itR; if (itL->first == k) { l[k] = f(itL->second, a); ++itL; ++itR; } else if (itL->first > k) { l[k] = a; ++itR; } else ++itL; } l.insert(itR, r.end()); } void addRefinement(RefinementMap& refis, const LValue& lvalue, TypeId ty) { refis[toString(lvalue)] = ty; } } // namespace Luau