TypePtr ConstantTable::check(const std::string &name, TypePtr type, bool coerce, AnalysisResultPtr ar, ConstructPtr construct, bool &present) { TypePtr actualType; present = true; if (name == "true" || name == "false") { actualType = Type::Boolean; } else if (!ar->isFirstPass() && m_values.find(name) == m_values.end()) { ClassScopePtr parent = findParent(ar, name); if (parent) { return parent->checkConst(name, type, coerce, ar, construct, present); } ar->getCodeError()->record(CodeError::UseUndeclaredConstant, construct); if (m_blockScope.is(BlockScope::ClassScope)) { actualType = Type::Variant; } else { actualType = Type::String; } setType(ar, name, actualType, true); present = false; } else { StringToTypePtrMap::const_iterator iter = m_coerced.find(name); if (iter != m_coerced.end()) { actualType = iter->second; if (actualType->is(Type::KindOfSome) || actualType->is(Type::KindOfAny)) { setType(ar, name, type, true); return type; } } else { ClassScopePtr parent = findParent(ar, name); if (parent) { return parent->checkConst(name, type, coerce, ar, construct, present); } present = false; actualType = NEW_TYPE(Some); setType(ar, name, actualType, true); m_declarations[name] = construct; } } if (Type::IsBadTypeConversion(ar, actualType, type, coerce)) { ar->getCodeError()->record(construct, type->getKindOf(), actualType->getKindOf()); } return actualType; }
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 ClassConstantExpression::inferTypes(AnalysisResultPtr ar, TypePtr type, bool coerce) { m_valid = false; ConstructPtr self = shared_from_this(); ClassScopePtr cls = ar->resolveClass(m_className); if (!cls || cls->isRedeclaring()) { if (cls) { m_redeclared = true; ar->getScope()->getVariables()-> setAttribute(VariableTable::NeedGlobalPointer); } if (!cls && ar->isFirstPass()) { ar->getCodeError()->record(self, CodeError::UnknownClass, self); } return type; } if (cls->getConstants()->isDynamic(m_varName)) { ar->getScope()->getVariables()-> setAttribute(VariableTable::NeedGlobalPointer); } if (cls->getConstants()->isExplicitlyDeclared(m_varName)) { string name = m_className + "::" + m_varName; ConstructPtr decl = cls->getConstants()->getDeclaration(m_varName); if (decl) { // No decl means an extension class. ar->getDependencyGraph()->add(DependencyGraph::KindOfConstant, ar->getName(), name, shared_from_this(), name, decl); } m_valid = true; } bool present; TypePtr t = cls->checkConst(m_varName, type, coerce, ar, shared_from_this(), present); if (present) { m_valid = true; } return t; }