void ClassStatement::getAllParents(AnalysisResultConstPtr ar, std::vector<std::string> &names) { if (!m_parent.empty()) { ClassScopePtr cls = ar->findClass(m_parent); if (cls) { if (!cls->isRedeclaring()) { cls->getAllParents(ar, names); } names.push_back(m_originalParent); } } if (m_base) { vector<string> bases; m_base->getStrings(bases); for (unsigned int i = 0; i < bases.size(); i++) { ClassScopePtr cls = ar->findClass(bases[i]); if (cls) { cls->getAllParents(ar, names); names.push_back(cls->getOriginalName()); } } } }
bool ClassScope::needsInvokeParent(AnalysisResultConstPtr ar, bool considerSelf /* = true */) { // check all functions this class has if (considerSelf) { for (const auto& func : m_functionsVec) { if (func->isPrivate()) return true; } } // walk up if (!m_parent.empty()) { ClassScopePtr super = ar->findClass(m_parent); return !super || super->isRedeclaring() || super->needsInvokeParent(ar); } return false; }
bool ClassScope::needsInvokeParent(AnalysisResultConstPtr ar, bool considerSelf /* = true */) { // check all functions this class has if (considerSelf) { for (FunctionScopePtrVec::const_iterator iter = m_functionsVec.begin(); iter != m_functionsVec.end(); ++iter) { if ((*iter)->isPrivate()) return true; } } // walk up if (!m_parent.empty()) { ClassScopePtr super = ar->findClass(m_parent); return !super || super->isRedeclaring() || super->needsInvokeParent(ar); } return false; }
bool ClassScope::derivesFrom(AnalysisResultConstPtr ar, const std::string &base, bool strict, bool def) const { if (derivesDirectlyFrom(base)) return true; for (std::string base_i: m_bases) { ClassScopePtr cl = ar->findClass(base_i); if (cl) { if (strict && cl->isRedeclaring()) { if (def) return true; continue; } if (cl->derivesFrom(ar, base, strict, def)) return true; } } return false; }
void ClassScope::setStaticDynamic(AnalysisResultConstPtr ar) { for (FunctionScopePtrVec::const_iterator iter = m_functionsVec.begin(); iter != m_functionsVec.end(); ++iter) { FunctionScopePtr fs = *iter; if (fs->isStatic()) fs->setDynamic(); } if (!m_parent.empty()) { if (derivesFromRedeclaring() == Derivation::Redeclaring) { const ClassScopePtrVec &parents = ar->findRedeclaredClasses(m_parent); for (ClassScopePtr cl: parents) { cl->setStaticDynamic(ar); } } else { ClassScopePtr parent = ar->findClass(m_parent); if (parent) { parent->setStaticDynamic(ar); } } } }
void ClassScope::setDynamic(AnalysisResultConstPtr ar, const std::string &name) { StringToFunctionScopePtrMap::const_iterator iter = m_functions.find(name); if (iter != m_functions.end()) { FunctionScopePtr fs = iter->second; fs->setDynamic(); } else if (!m_parent.empty()) { if (derivesFromRedeclaring() == Derivation::Redeclaring) { const ClassScopePtrVec &parents = ar->findRedeclaredClasses(m_parent); for (ClassScopePtr cl: parents) { cl->setDynamic(ar, name); } } else { ClassScopePtr parent = ar->findClass(m_parent); if (parent) { parent->setDynamic(ar, name); } } } }
ClassScopePtr ClassScope::FindCommonParent(AnalysisResultConstPtr ar, const std::string &cn1, const std::string &cn2) { ClassScopePtr cls1 = ar->findClass(cn1); ClassScopePtr cls2 = ar->findClass(cn2); if (!cls1 || !cls2) return ClassScopePtr(); if (cls1->isNamed(cls2->getScopeName())) return cls1; if (cls1->derivesFrom(ar, cn2, true, false)) return cls2; if (cls2->derivesFrom(ar, cn1, true, false)) return cls1; // walk up the class hierarchy. for (const std::string &base1: cls1->m_bases) { for (const std::string &base2: cls2->m_bases) { ClassScopePtr parent = FindCommonParent(ar, base1, base2); if (parent) return parent; } } return ClassScopePtr(); }
FunctionScopePtr ClassScope::findFunction(AnalysisResultConstPtr ar, const std::string &name, bool recursive, bool exclIntfBase /* = false */) { assert(toLower(name) == name); StringToFunctionScopePtrMap::const_iterator iter; iter = m_functions.find(name); if (iter != m_functions.end()) { assert(iter->second); return iter->second; } // walk up if (recursive) { int s = m_bases.size(); for (int i = 0; i < s; i++) { const string &base = m_bases[i]; ClassScopePtr super = ar->findClass(base); if (!super) continue; if (exclIntfBase && super->isInterface()) break; if (super->isRedeclaring()) { if (base == m_parent) { m_derivesFromRedeclaring = Derivation::Redeclaring; break; } continue; } FunctionScopePtr func = super->findFunction(ar, name, true, exclIntfBase); if (func) return func; } } if (!Option::AllDynamic && derivesFromRedeclaring() == Derivation::Redeclaring) { setDynamic(ar, name); } return FunctionScopePtr(); }
TypePtr ConstantTable::checkBases(const std::string &name, TypePtr type, bool coerce, AnalysisResultConstPtr ar, ConstructPtr construct, const std::vector<std::string> &bases, BlockScope *&defScope) { TypePtr actualType; defScope = NULL; ClassScopePtr parent = findParent(ar, name); if (parent) { actualType = parent->checkConst(name, type, coerce, ar, construct, parent->getBases(), defScope); if (defScope) return actualType; } for (int i = bases.size() - 1; i >= (parent ? 1 : 0); i--) { const string &base = bases[i]; ClassScopePtr super = ar->findClass(base); if (!super) continue; actualType = super->checkConst(name, type, coerce, ar, construct, super->getBases(), defScope); if (defScope) return actualType; } return actualType; }
TypePtr Type::Intersection(AnalysisResultConstPtr ar, TypePtr from, TypePtr to) { // Special case: if we're casting to Some or Any, return the "from" type; // if we're casting to Variant, return Variant. if (to->m_kindOf == KindOfSome || to->m_kindOf == KindOfAny) { return from; } else if (to->m_kindOf == KindOfVariant) { return Variant; } int resultKind = to->m_kindOf & from->m_kindOf; std::string resultName = ""; if (resultKind & KindOfObject) { // if they're the same, or we don't know one's name, then use // the other if (to->m_name == from->m_name || from->m_name.empty()) { resultName = to->m_name; } else if (to->m_name.empty()) { resultName = from->m_name; } else { // make sure there's a subclass relation ClassScopePtr cls = ar->findClass(from->m_name); if (cls) { if (cls->derivesFrom(ar, to->m_name, true, false)) { resultName = to->m_name; } else { resultKind &= ~KindOfObject; } } } } TypePtr res; // If there is overlap (for instance, they were the same, or we've narrowed // down something like Sequenece to be more specific), then return the // intersection of the types. if (resultKind) { res = TypePtr(new Type((KindOf)resultKind, resultName)); } else if (from->mustBe(KindOfObject) && to->m_kindOf == KindOfPrimitive) { // Special case Object -> Primitive: can we tostring it? if (!from->m_name.empty()) { ClassScopePtr cls = ar->findClass(from->m_name); if (cls && cls->findFunction(ar, "__tostring", true)) { res = Type::String; } } // Otherwise, return Int32 res = Int32; } else if (from->m_kindOf == KindOfBoolean && to->mustBe(KindOfNumeric | KindOfArray | KindOfString) && !IsExactType(to->m_kindOf)) { res = Int32; } else { res = to; } if (from->mustBe(KindOfBoolean) && to->m_kindOf == KindOfPrimitive) { res = Int32; } return res; }
TypePtr Type::Coerce(AnalysisResultConstPtr ar, TypePtr type1, TypePtr type2) { if (SameType(type1, type2)) return type1; if (type1->m_kindOf == KindOfVariant || type2->m_kindOf == KindOfVariant) return Type::Variant; if (type1->m_kindOf > type2->m_kindOf) { TypePtr tmp = type1; type1 = type2; type2 = tmp; } if (type1->m_kindOf == KindOfVoid && (type2->m_kindOf == KindOfString || type2->m_kindOf == KindOfArray || type2->m_kindOf == KindOfObject)) { return type2; } if (type2->m_kindOf == KindOfSome || type2->m_kindOf == KindOfAny) return type1; if (type2->m_kindOf & KindOfAuto) { if (type1->mustBe(type2->m_kindOf & ~KindOfAuto)) { if (!(type1->m_kindOf & Type::KindOfString)) { return type1; } if (type2->m_kindOf == KindOfAutoSequence) { return Type::Sequence; } return GetType((KindOf)(type2->m_kindOf & ~KindOfAuto)); } return Type::Variant; } if (type1->mustBe(KindOfInteger)) { if (type2->mustBe(KindOfInteger)) { return type2; } else if (type2->mustBe(KindOfDouble)) { return Type::Numeric; } } if (type1->mustBe(Type::KindOfObject) && type2->mustBe(Type::KindOfObject)) { if (type1->m_name.empty()) return type1; if (type2->m_name.empty()) return type2; ClassScopePtr cls1 = ar->findClass(type1->m_name); if (cls1 && !cls1->isRedeclaring() && cls1->derivesFrom(ar, type2->m_name, true, false)) { return type2; } ClassScopePtr cls2 = ar->findClass(type2->m_name); if (cls2 && !cls2->isRedeclaring() && cls2->derivesFrom(ar, type1->m_name, true, false)) { return type1; } if (cls1 && cls2 && !cls1->isRedeclaring() && !cls2->isRedeclaring()) { ClassScopePtr parent = ClassScope::FindCommonParent(ar, type1->m_name, type2->m_name); if (parent) { return Type::CreateObjectType(parent->getName()); } } return Type::Object; } if (type1->mustBe(type2->m_kindOf)) { return type2; } CT_ASSERT(Type::KindOfString < Type::KindOfArray); if (type1->m_kindOf == Type::KindOfString && type2->m_kindOf == Type::KindOfArray) { return Type::Sequence; } return Type::Variant; }
ClassScopePtr ClassScope::getParentScope(AnalysisResultConstPtr ar) const { if (m_parent.empty()) return ClassScopePtr(); return ar->findClass(m_parent); }