void ArrayElementExpression::analyzeProgram(AnalysisResultPtr ar) {
  m_variable->analyzeProgram(ar);
  if (m_offset) m_offset->analyzeProgram(ar);
  if (ar->getPhase() == AnalysisResult::AnalyzeFinal) {
    if (!m_global && (m_context & AccessContext) &&
        !(m_context & (LValue|RefValue|DeepReference|
                       UnsetContext|RefParameter|InvokeArgument))) {
      TypePtr type = m_variable->getActualType();
      if (!type ||
          (!type->is(Type::KindOfString) && !type->is(Type::KindOfArray))) {
        FunctionScopePtr scope = getFunctionScope();
        if (scope) scope->setNeedsRefTemp();
      }
    }
    if (m_global) {
      if (getContext() & (LValue|RefValue|DeepReference)) {
        setContext(NoLValueWrapper);
      } else if (!m_dynamicGlobal &&
          !(getContext() &
            (LValue|RefValue|RefParameter|DeepReference|
             UnsetContext|ExistContext))) {
        VariableTablePtr vars = ar->getVariables();
        Symbol *sym = vars->getSymbol(m_globalName);
        if (!sym || sym->getDeclaration().get() == this) {
          Compiler::Error(Compiler::UseUndeclaredVariable, shared_from_this());
        }
      }
    }
  }
}
void ObjectPropertyExpression::analyzeProgram(AnalysisResultPtr ar) {
  m_object->analyzeProgram(ar);
  m_property->analyzeProgram(ar);
  if (ar->getPhase() == AnalysisResult::AnalyzeFinal) {
    if (!m_valid && m_context & (LValue|RefValue|DeepReference|UnsetContext)) {
      FunctionScopePtr func = getFunctionScope();
      if (func) func->setNeedsRefTemp();
    }
  }
}
void ArrayElementExpression::analyzeProgram(AnalysisResultPtr ar) {
  m_variable->analyzeProgram(ar);
  if (m_offset) m_offset->analyzeProgram(ar);
  if (ar->getPhase() == AnalysisResult::AnalyzeFinal) {
    if (!m_global && (m_context & AccessContext) &&
        !(m_context & (LValue|RefValue|DeepReference|
                       UnsetContext|RefParameter|InvokeArgument))) {
      TypePtr type = m_variable->getActualType();
      if (!type ||
          (!type->is(Type::KindOfString) && !type->is(Type::KindOfArray))) {
        FunctionScopePtr scope = getFunctionScope();
        if (scope && !needsCSE()) scope->setNeedsRefTemp();
      }
    }
    if (m_global) {
      if (getContext() & (LValue|RefValue|DeepReference)) {
        setContext(NoLValueWrapper);
      } else if (!m_dynamicGlobal &&
          !(getContext() &
            (LValue|RefValue|RefParameter|DeepReference|
             UnsetContext|ExistContext))) {
        VariableTablePtr vars = ar->getVariables();
        Symbol *sym = vars->getSymbol(m_globalName);
        if (!sym || sym->getDeclaration().get() == this) {
          Compiler::Error(Compiler::UseUndeclaredGlobalVariable,
                          shared_from_this());
        }
      }
      FunctionScopePtr scope = getFunctionScope();
      if (scope) scope->setNeedsCheckMem();
    } else {
      TypePtr at(m_variable->getActualType());
      TypePtr et(m_variable->getExpectedType());
      if (et &&
          (et->is(Type::KindOfSequence) ||
           et->is(Type::KindOfAutoSequence)) &&
          at && at->isExactType()) {
        // since Sequence maps to Variant in the runtime,
        // using Sequence for the expected type will
        // never allow the necessary casts to be generated.
        m_variable->setExpectedType(at);
      }
    }
  }
}