TypePtr VariableTable::setType(AnalysisResultConstPtr ar, Symbol *sym, TypePtr type, bool coerce) { bool force_coerce = coerce; int mask = GetVarClassMaskForSym(sym); if (m_forcedVariants & mask && !sym->isHidden()) { type = Type::Variant; force_coerce = true; } TypePtr ret = SymbolTable::setType(ar, sym, type, force_coerce); if (!ret) return ret; if (sym->isGlobal() && !isGlobalTable(ar)) { ar->lock()->getVariables()->setType(ar, sym->getName(), type, coerce); } if (coerce) { if (sym->isParameter()) { FunctionScope *func = dynamic_cast<FunctionScope *>(&m_blockScope); assert(func); TypePtr paramType = func->setParamType(ar, sym->getParameterIndex(), type); if (!Type::SameType(paramType, type)) { return setType(ar, sym, paramType, true); // recursively } } } return ret; }
TypePtr VariableTable::add(Symbol *sym, TypePtr type, bool implicit, AnalysisResultConstPtr ar, ConstructPtr construct, ModifierExpressionPtr modifiers) { if (getAttribute(InsideStaticStatement)) { addStaticVariable(sym, ar); if (ClassScope::NeedStaticArray(getClassScope(), getFunctionScope())) { forceVariant(ar, sym->getName(), AnyVars); } } else if (getAttribute(InsideGlobalStatement)) { sym->setGlobal(); m_hasGlobal = true; AnalysisResult::Locker lock(ar); if (!isGlobalTable(ar)) { lock->getVariables()->add(sym->getName(), type, implicit, ar, construct, modifiers); } assert(type->is(Type::KindOfSome) || type->is(Type::KindOfAny)); TypePtr varType = ar->getVariables()->getFinalType(sym->getName()); if (varType) { type = varType; } else { lock->getVariables()->setType(ar, sym->getName(), type, true); } } else if (!sym->isHidden() && isPseudoMainTable()) { // A variable used in a pseudomain // only need to do this once... should mark the sym. ar->lock()->getVariables()->add(sym->getName(), type, implicit, ar, construct, modifiers); } if (modifiers) { if (modifiers->isProtected()) { sym->setProtected(); } else if (modifiers->isPrivate()) { sym->setPrivate(); m_hasPrivate = true; if (!sym->isStatic() && !modifiers->isStatic()) { m_hasNonStaticPrivate = true; } } if (modifiers->isStatic()) { addStaticVariable(sym, ar); } } type = setType(ar, sym, type, true); sym->setDeclaration(construct); if (!implicit && m_blockScope.isFirstPass()) { if (!sym->getValue()) { sym->setValue(construct); } } return type; }
void VariableTable::addStaticVariable(Symbol *sym, AnalysisResultConstPtr ar, bool member /* = false */) { if (isGlobalTable(ar) || sym->isStatic()) { return; // a static variable at global scope is the same as non-static } addStaticVariable(sym, ar->lock().get(), member); }
TypePtr VariableTable::checkVariable(Symbol *sym, TypePtr type, bool coerce, AnalysisResultConstPtr ar, ConstructPtr construct) { // Variable used in pseudomain if (!sym->isHidden() && isPseudoMainTable()) { // only need to do this once... should mark the sym. ar->lock()->getVariables()->checkVariable(sym->getName(), type, coerce, ar, construct); } if (!sym->declarationSet()) { type = setType(ar, sym, type, coerce); sym->setDeclaration(construct); return type; } return setType(ar, sym, type, coerce); }