void SimpleVariable::outputCPPImpl(CodeGenerator &cg, AnalysisResultPtr ar) { if (m_this) { ASSERT((getContext() & ObjectContext) == 0); if (hasContext(OprLValue) || hasContext(AssignmentLHS)) { cg_printf("throw_assign_this()"); } else if (hasContext(DeepOprLValue) || hasContext(DeepAssignmentLHS) || hasContext(LValue)) { // $this[] op= ...; or $this[] = ... cg_printf("Variant(GET_THIS())"); } else { ClassScopePtr cls = getOriginalClass(); if (cls->derivedByDynamic()) { cg_printf("Object(GET_THIS())"); } else { cg_printf("GET_THIS_TYPED(%s)", cls->getId(cg).c_str()); } } } else if (m_superGlobal) { VariableTablePtr variables = getScope()->getVariables(); string name = variables->getGlobalVariableName(cg, ar, m_name); cg_printf("g->%s", name.c_str()); } else if (m_globals) { cg_printf("get_global_array_wrapper()"); } else { const char *prefix = getScope()->getVariables()->getVariablePrefix(m_sym); cg_printf("%s%s", prefix, cg.formatLabel(m_name).c_str()); } }
void ClosureExpression::analyzeVars(AnalysisResultPtr ar) { m_values->analyzeProgram(ar); if (ar->getPhase() == AnalysisResult::AnalyzeAll) { getFunctionScope()->addUse(m_func->getFunctionScope(), BlockScope::UseKindClosure); m_func->getFunctionScope()->setClosureVars(m_vars); // closure function's variable table (not containing function's) VariableTablePtr variables = m_func->getFunctionScope()->getVariables(); VariableTablePtr containing = getFunctionScope()->getVariables(); for (int i = 0; i < m_vars->getCount(); i++) { auto param = dynamic_pointer_cast<ParameterExpression>((*m_vars)[i]); auto const& name = param->getName(); { Symbol *containingSym = containing->addDeclaredSymbol(name, param); containingSym->setPassClosureVar(); Symbol *sym = variables->addDeclaredSymbol(name, param); sym->setClosureVar(); sym->setDeclaration(ConstructPtr()); if (param->isRef()) { sym->setRefClosureVar(); } else { sym->clearRefClosureVar(); } } } return; } }
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 FunctionScope::RecordFunctionInfo(std::string fname, FunctionScopePtr func) { VariableTablePtr variables = func->getVariables(); if (Option::WholeProgram) { Lock lock(s_refParamInfoLock); FunctionInfoPtr &info = s_refParamInfo[fname]; if (!info) { info = std::make_shared<FunctionInfo>(); } if (func->isStatic()) { info->setMaybeStatic(); } if (func->isRefReturn()) { info->setMaybeRefReturn(); } if (func->isReferenceVariableArgument()) { info->setRefVarArg(func->getMaxParamCount()); } for (int i = 0; i < func->getMaxParamCount(); i++) { if (func->isRefParam(i)) info->setRefParam(i); } } auto limit = func->getDeclParamCount(); for (int i = 0; i < limit; i++) { variables->addParam(func->getParamName(i), AnalysisResultPtr(), ConstructPtr()); } }
void MethodStatement::addParamRTTI(AnalysisResultPtr ar) { FunctionScopePtr func = dynamic_pointer_cast<FunctionScope>(ar->getScope()); VariableTablePtr variables = func->getVariables(); if (variables->getAttribute(VariableTable::ContainsDynamicVariable) || variables->getAttribute(VariableTable::ContainsExtract)) { return; } for (int i = 0; i < m_params->getCount(); i++) { ParameterExpressionPtr param = dynamic_pointer_cast<ParameterExpression>((*m_params)[i]); const string ¶mName = param->getName(); if (variables->isLvalParam(paramName)) continue; TypePtr paramType = param->getActualType(); if ((paramType->is(Type::KindOfVariant) || paramType->is(Type::KindOfSome)) && !param->isRef()) { param->setHasRTTI(); ClassScopePtr cls = ar->getClassScope(); ar->addParamRTTIEntry(cls, func, paramName); const string funcId = ar->getFuncId(cls, func); ar->addRTTIFunction(funcId); } } }
void ClassStatement::outputCPPClassDecl(CodeGenerator &cg, AnalysisResultPtr ar, const char *clsName, const char *originalName, const char *parent) { ClassScopeRawPtr classScope = getClassScope(); VariableTablePtr variables = classScope->getVariables(); ConstantTablePtr constants = classScope->getConstants(); const char *sweep = classScope->isUserClass() && !classScope->isSepExtension() ? "_NO_SWEEP" : ""; if (variables->hasAllJumpTables() && classScope->hasAllJumpTables()) { cg_printf("DECLARE_CLASS%s(%s, %s, %s)\n", sweep, clsName, CodeGenerator::EscapeLabel(originalName).c_str(), parent); return; } // Now we start to break down DECLARE_CLASS into lines of code that could // be generated differently... cg_printf("DECLARE_CLASS_COMMON%s(%s, %s)\n", sweep, clsName, CodeGenerator::EscapeLabel(originalName).c_str()); }
std::string SimpleVariable::getAssignableCPPVariable(AnalysisResultPtr ar) const { VariableTablePtr variables = getScope()->getVariables(); if (m_this) { if (!hasAnyContext(OprLValue | AssignmentLHS) && variables->getAttribute(VariableTable::ContainsLDynamicVariable)) { ASSERT(m_sym); const string &namePrefix = getNamePrefix(); return namePrefix + variables->getVariablePrefix(m_sym) + "this"; } return ""; } else if (m_superGlobal) { const string &name = variables->getGlobalVariableName(ar, m_name); return string("g->") + name.c_str(); } else if (m_globals) { return "get_global_array_wrapper()"; } else { ASSERT(m_sym); const string &prefix0 = getNamePrefix(); const char *prefix1 = getScope()->getVariables()->getVariablePrefix(m_sym); return prefix0 + prefix1 + CodeGenerator::FormatLabel(m_name); } }
TypePtr ClosureExpression::inferTypes(AnalysisResultPtr ar, TypePtr type, bool coerce) { if (m_vars) { assert(m_values && m_values->getCount() == m_vars->getCount()); // containing function's variable table (not closure function's) VariableTablePtr variables = getScope()->getVariables(); // closure function's variable table VariableTablePtr cvariables = m_func->getFunctionScope()->getVariables(); // force all reference use vars into variant for this function scope for (int i = 0; i < m_vars->getCount(); i++) { ParameterExpressionPtr param = dynamic_pointer_cast<ParameterExpression>((*m_vars)[i]); const string &name = param->getName(); if (param->isRef()) { variables->forceVariant(ar, name, VariableTable::AnyVars); } } // infer the types of the values m_values->inferAndCheck(ar, Type::Some, false); // coerce the types inferred from m_values into m_vars for (int i = 0; i < m_vars->getCount(); i++) { ExpressionPtr value = (*m_values)[i]; ParameterExpressionPtr var = dynamic_pointer_cast<ParameterExpression>((*m_vars)[i]); assert(!var->getExpectedType()); assert(!var->getImplementedType()); if (var->isRef()) { var->setActualType(Type::Variant); } else { TypePtr origVarType(var->getActualType() ? var->getActualType() : Type::Some); var->setActualType(Type::Coerce(ar, origVarType, value->getType())); } } { // this lock isn't technically needed for thread-safety, since // the dependencies are all set up. however, the lock assertions // will fail if we don't acquire it. GET_LOCK(m_func->getFunctionScope()); // bootstrap the closure function's variable table with // the types from m_vars for (int i = 0; i < m_vars->getCount(); i++) { ParameterExpressionPtr param = dynamic_pointer_cast<ParameterExpression>((*m_vars)[i]); const string &name = param->getName(); cvariables->addParamLike(name, param->getType(), ar, shared_from_this(), getScope()->isFirstPass()); } } } return s_ClosureType; }
void CatchStatement::inferTypes(AnalysisResultPtr ar) { ClassScopePtr cls = ar->findClass(m_className); TypePtr type; m_valid = cls; if (!m_valid) { if (ar->isFirstPass()) { ConstructPtr self = shared_from_this(); ar->getCodeError()->record(self, CodeError::UnknownClass, self); } type = NEW_TYPE(Object); } else if (cls->isRedeclaring()) { type = NEW_TYPE(Object); } else { type = Type::CreateObjectType(m_className); } BlockScopePtr scope = ar->getScope(); VariableTablePtr variables = scope->getVariables(); variables->add(m_variable, type, false, ar, shared_from_this(), ModifierExpressionPtr(), false); if (ar->isFirstPass()) { FunctionScopePtr func = dynamic_pointer_cast<FunctionScope>(scope); if (func && variables->isParameter(m_variable)) { variables->addLvalParam(m_variable); } } if (m_stmt) m_stmt->inferTypes(ar); }
void ClassVariable::onParseRecur(AnalysisResultConstPtr ar, ClassScopePtr scope) { ModifierExpressionPtr modifiers = scope->setModifiers(m_modifiers); for (int i = 0; i < m_declaration->getCount(); i++) { VariableTablePtr variables = scope->getVariables(); ExpressionPtr exp = (*m_declaration)[i]; if (exp->is(Expression::KindOfAssignmentExpression)) { AssignmentExpressionPtr assignment = dynamic_pointer_cast<AssignmentExpression>(exp); ExpressionPtr var = assignment->getVariable(); const std::string &name = dynamic_pointer_cast<SimpleVariable>(var)->getName(); if (variables->isPresent(name)) { Compiler::Error(Compiler::DeclaredVariableTwice, exp); m_declaration->removeElement(i--); } else { assignment->onParseRecur(ar, scope); } } else { const std::string &name = dynamic_pointer_cast<SimpleVariable>(exp)->getName(); if (variables->isPresent(name)) { Compiler::Error(Compiler::DeclaredVariableTwice, exp); m_declaration->removeElement(i--); } else { variables->add(name, Type::Variant, false, ar, exp, m_modifiers); } } } scope->setModifiers(modifiers); }
void ClassVariable::onParse(AnalysisResultPtr ar) { ModifierExpressionPtr modifiers = ar->getScope()->setModifiers(m_modifiers); for (int i = 0; i < m_declaration->getCount(); i++) { VariableTablePtr variables = ar->getScope()->getVariables(); ExpressionPtr exp = (*m_declaration)[i]; if (exp->is(Expression::KindOfAssignmentExpression)) { AssignmentExpressionPtr assignment = dynamic_pointer_cast<AssignmentExpression>(exp); ExpressionPtr var = assignment->getVariable(); const std::string &name = dynamic_pointer_cast<SimpleVariable>(var)->getName(); if (variables->isPresent(name)) { ar->getCodeError()->record(CodeError::DeclaredVariableTwice, exp); } IParseHandlerPtr ph = dynamic_pointer_cast<IParseHandler>(exp); ph->onParse(ar); } else { const std::string &name = dynamic_pointer_cast<SimpleVariable>(exp)->getName(); if (variables->isPresent(name)) { ar->getCodeError()->record(CodeError::DeclaredVariableTwice, exp); } variables->add(name, TypePtr(), false, ar, exp, m_modifiers); } } ar->getScope()->setModifiers(modifiers); }
TypePtr ParameterExpression::inferTypes(AnalysisResultPtr ar, TypePtr type, bool coerce) { assert(type->is(Type::KindOfSome) || type->is(Type::KindOfAny)); TypePtr ret = getTypeSpec(ar, true); VariableTablePtr variables = getScope()->getVariables(); // Functions that can be called dynamically have to have // variant parameters, even if they have a type hint if ((Option::AllDynamic || getFunctionScope()->isDynamic()) || getFunctionScope()->isRedeclaring() || getFunctionScope()->isVirtual()) { if (!Option::HardTypeHints || !ret->isExactType()) { variables->forceVariant(ar, m_name, VariableTable::AnyVars); ret = Type::Variant; } } if (m_defaultValue && !m_ref) { TypePtr r = m_defaultValue->inferAndCheck(ar, Type::Some, false); if (!m_defaultValue->is(KindOfConstantExpression) || !static_pointer_cast<ConstantExpression>(m_defaultValue)->isNull()) { ret = Type::Coerce(ar, r, ret); } } // parameters are like variables, but we need to remember these are // parameters so when variable table is generated, they are not generated // as declared variables. return variables->addParamLike(m_name, ret, ar, shared_from_this(), getScope()->isFirstPass()); }
void ArrayElementExpression::analyzeProgram(AnalysisResultPtr ar) { m_variable->analyzeProgram(ar); if (m_offset) m_offset->analyzeProgram(ar); if (ar->getPhase() == AnalysisResult::AnalyzeFinal) { 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()); } } } 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); } } } }
void GlobalStatement::outputCPP(CodeGenerator &cg, AnalysisResultPtr ar) { if (m_dynamicGlobal) { cg.printf("throw_fatal(\"dynamic global\");\n"); } else if (!ar->getScope()->inPseudoMain() || !isTopLevel()) { BlockScopePtr scope = ar->getScope(); if (m_exp->getCount() > 1) cg.indentBegin("{\n"); for (int i = 0; i < m_exp->getCount(); i++) { ExpressionPtr exp = (*m_exp)[i]; if (exp->is(Expression::KindOfSimpleVariable)) { SimpleVariablePtr var = dynamic_pointer_cast<SimpleVariable>(exp); const string &name = var->getName(); VariableTablePtr variables = scope->getVariables(); if (variables->needLocalCopy(name)) { cg.printf("%s%s = ref(g->%s);\n", Option::VariablePrefix, name.c_str(), variables->getGlobalVariableName(ar, name).c_str()); } } else { // type inference should have set m_dynamicGlobal to true. ASSERT(false); } } if (m_exp->getCount() > 1) cg.indentEnd("}\n"); } }
void GlobalStatement::outputCPPImpl(CodeGenerator &cg, AnalysisResultPtr ar) { BlockScopePtr scope = getScope(); if (m_exp->getCount() > 1) cg_indentBegin("{\n"); for (int i = 0; i < m_exp->getCount(); i++) { ExpressionPtr exp = (*m_exp)[i]; if (exp->is(Expression::KindOfSimpleVariable)) { SimpleVariablePtr var = dynamic_pointer_cast<SimpleVariable>(exp); const string &name = var->getName(); VariableTablePtr variables = scope->getVariables(); if (variables->needLocalCopy(name)) { cg_printf("%s%s = ref(g->%s);\n", Option::VariablePrefix, name.c_str(), variables->getGlobalVariableName(cg, ar, name).c_str()); } } else if (exp->is(Expression::KindOfDynamicVariable)) { DynamicVariablePtr var = dynamic_pointer_cast<DynamicVariable>(exp); ExpressionPtr exp = var->getSubExpression(); exp->outputCPPBegin(cg, ar); int id = cg.createNewLocalId(shared_from_this()); cg_printf("CStrRef dgv_%d((", id); exp->outputCPP(cg, ar); cg_printf("));\n"); cg_printf("variables->get(dgv_%d) = ref(g->get(dgv_%d));\n", id, id); exp->outputCPPEnd(cg, ar); } else { assert(false); } } if (m_exp->getCount() > 1) cg_indentEnd("}\n"); }
TypePtr AssignmentExpression:: inferTypesImpl(AnalysisResultPtr ar, TypePtr type, bool coerce, ExpressionPtr variable, ExpressionPtr value /* = ExpressionPtr() */) { TypePtr ret = type; if (value) { if (coerce) { ret = value->inferAndCheck(ar, type, coerce); } else { ret = value->inferAndCheck(ar, NEW_TYPE(Some), coerce); } } BlockScopePtr scope = ar->getScope(); if (variable->is(Expression::KindOfConstantExpression)) { // ...as in ClassConstant statement ConstantExpressionPtr exp = dynamic_pointer_cast<ConstantExpression>(variable); bool p; scope->getConstants()->check(exp->getName(), ret, true, ar, variable, p); } else if (variable->is(Expression::KindOfDynamicVariable)) { // simptodo: not too sure about this ar->getFileScope()->setAttribute(FileScope::ContainsLDynamicVariable); } else if (variable->is(Expression::KindOfSimpleVariable)) { SimpleVariablePtr var = dynamic_pointer_cast<SimpleVariable>(variable); if (var->getName() == "this" && ar->getClassScope()) { if (ar->isFirstPass()) { ar->getCodeError()->record(variable, CodeError::ReassignThis, variable); } } if (ar->getPhase() == AnalysisResult::LastInference && value) { if (!value->getExpectedType()) { value->setExpectedType(variable->getActualType()); } } } // if the value may involve object, consider the variable as "referenced" // so that objects are not destructed prematurely. bool referenced = true; if (value && value->isScalar()) referenced = false; if (ret && ret->isNoObjectInvolved()) referenced = false; if (referenced && variable->is(Expression::KindOfSimpleVariable)) { SimpleVariablePtr var = dynamic_pointer_cast<SimpleVariable>(variable); const std::string &name = var->getName(); VariableTablePtr variables = ar->getScope()->getVariables(); variables->addReferenced(name); } TypePtr vt = variable->inferAndCheck(ar, ret, true); if (!coerce && type->is(Type::KindOfAny)) { ret = vt; } return ret; }
void ExpressionList::optimize(AnalysisResultConstPtr ar) { bool changed = false; size_t i = m_exps.size(); if (m_kind != ListKindParam) { size_t skip = m_kind == ListKindLeft ? 0 : i - 1; while (i--) { if (i != skip) { ExpressionPtr &e = m_exps[i]; if (!e || e->getContainedEffects() == NoEffect) { removeElement(i); changed = true; } else if (e->is(KindOfExpressionList)) { ExpressionListPtr el(static_pointer_cast<ExpressionList>(e)); removeElement(i); for (size_t j = el->getCount(); j--; ) { insertElement((*el)[j], i); } changed = true; } else if (e->getLocalEffects() == NoEffect) { e = e->unneeded(); // changed already handled by unneeded } } } if (m_exps.size() == 1) { m_kind = ListKindWrapped; } else if (m_kind == ListKindLeft && m_exps[0]->isScalar()) { ExpressionPtr e = m_exps[0]; removeElement(0); addElement(e); m_kind = ListKindWrapped; } } else { if (hasContext(UnsetContext) && ar->getPhase() >= AnalysisResult::PostOptimize) { while (i--) { ExpressionPtr &e = m_exps[i]; if (e->is(Expression::KindOfSimpleVariable)) { SimpleVariablePtr var = dynamic_pointer_cast<SimpleVariable>(e); if (var->checkUnused()) { const std::string &name = var->getName(); VariableTablePtr variables = getScope()->getVariables(); if (!variables->isNeeded(name)) { removeElement(i); changed = true; } } } } } } if (changed) { getScope()->addUpdates(BlockScope::UseKindCaller); } }
void GlobalStatement::inferTypes(AnalysisResultPtr ar) { IMPLEMENT_INFER_AND_CHECK_ASSERT(getScope()); BlockScopePtr scope = getScope(); for (int i = 0; i < m_exp->getCount(); i++) { ExpressionPtr exp = (*m_exp)[i]; VariableTablePtr variables = scope->getVariables(); variables->setAttribute(VariableTable::NeedGlobalPointer); if (exp->is(Expression::KindOfSimpleVariable)) { SimpleVariablePtr var = dynamic_pointer_cast<SimpleVariable>(exp); const std::string &name = var->getName(); /* If we have already seen this variable in the current scope and it is not a global variable, record this variable as "redeclared" which will force Variant type. */ variables->setAttribute(VariableTable::InsideGlobalStatement); variables->checkRedeclared(name, KindOfGlobalStatement); variables->addLocalGlobal(name); var->setContext(Expression::Declaration); var->inferAndCheck(ar, Type::Any, true); variables->forceVariant(ar, name, VariableTable::AnyVars); variables->clearAttribute(VariableTable::InsideGlobalStatement); } else { variables->forceVariants(ar, VariableTable::AnyVars); variables->setAttribute(VariableTable::ContainsLDynamicVariable); assert(exp->is(Expression::KindOfDynamicVariable)); exp->inferAndCheck(ar, Type::Any, true); } } }
void CatchStatement::outputCPPImpl(CodeGenerator &cg, AnalysisResultPtr ar) { if (m_valid) { cg.indentBegin("if (e.instanceof(\"%s\")) {\n", m_className.c_str()); VariableTablePtr variables = ar->getScope()->getVariables(); cg.printf("%s = e;\n", variables->getVariableName(ar, m_variable).c_str()); } else { cg.indentBegin("if (false) {\n"); } if (m_stmt) m_stmt->outputCPP(cg, ar); cg.indentEnd("}"); }
bool ListAssignment::preOutputCPP(CodeGenerator &cg, AnalysisResultPtr ar, int state) { ASSERT(m_array); if (!cg.inExpression()) return true; if (m_variables) { preOutputVariables(cg, ar, m_variables->hasEffect() || m_array->hasEffect() ? FixOrder : 0); } m_array->preOutputCPP(cg, ar, 0); bool isArray = false, notArray = false; if (TypePtr type = m_array->getActualType()) { isArray = type->is(Type::KindOfArray); notArray = type->isPrimitive() || type->is(Type::KindOfString) || type->is(Type::KindOfObject); } m_cppTemp = genCPPTemp(cg, ar); cg.wrapExpressionBegin(); if (outputLineMap(cg, ar)) cg_printf("0);\n"); cg_printf("CVarRef %s((", m_cppTemp.c_str()); m_array->outputCPP(cg, ar); cg_printf("));\n"); std::string tmp; if (notArray) { tmp = "null"; } else { tmp = genCPPTemp(cg, ar); bool need_ref = true; if (m_array->is(Expression::KindOfSimpleVariable)) { std::string name = static_pointer_cast<SimpleVariable>(m_array)->getName(); VariableTablePtr variables = getScope()->getVariables(); if (variables->isParameter(name) && !variables->isLvalParam(name)) { need_ref = false; } } cg_printf("Variant %s((", tmp.c_str()); if (need_ref) cg_printf("ref("); cg_printf("%s",m_cppTemp.c_str()); if (need_ref) cg_printf(")"); cg_printf("));\n"); if (!isArray) { cg_printf("if (!f_is_array(%s)) %s.unset();\n",tmp.c_str(), tmp.c_str()); } } outputCPPAssignment(cg, ar, tmp); return true; }
void IncludeExpression::analyzeProgram(AnalysisResultPtr ar) { if (!m_include.empty()) { if (ar->getPhase() == AnalysisResult::AnalyzeAll || ar->getPhase() == AnalysisResult::AnalyzeFinal) { analyzeInclude(ar, m_include); } } VariableTablePtr var = getScope()->getVariables(); var->setAttribute(VariableTable::ContainsLDynamicVariable); UnaryOpExpression::analyzeProgram(ar); }
void ParameterExpression::outputCPPImpl(CodeGenerator &cg, AnalysisResultPtr ar) { FunctionScopePtr func = dynamic_pointer_cast<FunctionScope>(ar->getScope()); VariableTablePtr variables = func->getVariables(); TypePtr paramType = func->getParamType(cg.getItemIndex()); bool isCVarRef = false; if (cg.getContext() == CodeGenerator::CppStaticMethodWrapper || (!variables->isLvalParam(m_name) && !variables->getAttribute(VariableTable::ContainsDynamicVariable) && !variables->getAttribute(VariableTable::ContainsExtract) && !m_ref)) { if (paramType->is(Type::KindOfVariant) || paramType->is(Type::KindOfSome)) { cg_printf("CVarRef"); isCVarRef = true; } else if (paramType->is(Type::KindOfArray)) cg_printf("CArrRef"); else if (paramType->is(Type::KindOfString)) cg_printf("CStrRef"); else paramType->outputCPPDecl(cg, ar); } else { paramType->outputCPPDecl(cg, ar); } cg_printf(" %s%s", Option::VariablePrefix, m_name.c_str()); if (m_defaultValue) { CodeGenerator::Context context = cg.getContext(); bool comment = context == CodeGenerator::CppImplementation || (context == CodeGenerator::CppDeclaration && func->isInlined()); if (comment) { cg_printf(" // "); } cg_printf(" = "); ConstantExpressionPtr con = dynamic_pointer_cast<ConstantExpression>(m_defaultValue); if (isCVarRef && con && con->isNull()) { cg_printf("null_variant"); } else { if (comment) { cg.setContext(CodeGenerator::CppParameterDefaultValueImpl); } else { cg.setContext(CodeGenerator::CppParameterDefaultValueDecl); } m_defaultValue->outputCPP(cg, ar); cg.setContext(context); } if (comment) { cg_printf("\n"); } } }
void StaticStatement::outputCPPImpl(CodeGenerator &cg, AnalysisResultPtr ar) { BlockScopePtr scope = getScope(); if (scope->inPseudoMain()) { if (m_exp->getCount() > 1) cg_indentBegin("{\n"); for (int i = 0; i < m_exp->getCount(); i++) { ExpressionPtr exp = (*m_exp)[i]; if (exp->is(Expression::KindOfAssignmentExpression)) { exp->outputCPP(cg, ar); cg_printf(";\n"); } else { ASSERT(false); } } if (m_exp->getCount() > 1) cg_indentEnd("}\n"); return; } VariableTablePtr variables = scope->getVariables(); if (m_exp->getCount() > 1) cg_indentBegin("{\n"); for (int i = 0; i < m_exp->getCount(); i++) { ExpressionPtr exp = (*m_exp)[i]; if (exp->is(Expression::KindOfAssignmentExpression)) { AssignmentExpressionPtr assignment_exp = dynamic_pointer_cast<AssignmentExpression>(exp); ExpressionPtr variable = assignment_exp->getVariable(); SimpleVariablePtr var = dynamic_pointer_cast<SimpleVariable>(variable); assert(var->hasContext(Expression::Declaration)); const std::string &name = var->getName(); if (variables->needLocalCopy(name)) { ASSERT(var->hasAssignableCPPVariable()); cg_printf("%s.assignRef(%s%s);\n", var->getAssignableCPPVariable(ar).c_str(), Option::StaticVariablePrefix, name.c_str()); } cg_indentBegin("if (!%s%s%s) {\n", Option::InitPrefix, Option::StaticVariablePrefix, name.c_str()); exp->outputCPP(cg, ar); cg_printf(";\n"); cg_printf("%s%s%s = true;\n", Option::InitPrefix, Option::StaticVariablePrefix, name.c_str()); cg_indentEnd("}\n"); } else { ASSERT(false); } } if (m_exp->getCount() > 1) cg_indentEnd("}\n"); }
void FunctionScope::getClosureUseVars( ParameterExpressionPtrIdxPairVec &useVars, bool filterUsed /* = true */) { useVars.clear(); if (!m_closureVars) return; assert(isClosure()); VariableTablePtr variables = getVariables(); for (int i = 0; i < m_closureVars->getCount(); i++) { auto param = dynamic_pointer_cast<ParameterExpression>((*m_closureVars)[i]); auto const& name = param->getName(); if (!filterUsed || variables->isUsed(name)) { useVars.push_back(ParameterExpressionPtrIdxPair(param, i)); } } }
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_dynamicGlobal && !(getContext() & (LValue|RefValue|RefParameter|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 BuiltinSymbols::LoadVariables(AnalysisResultPtr ar, VariableTablePtr variables) { assert(Loaded); if (s_variables) { variables->import(s_variables); } }
void IncludeExpression::analyzeProgram(AnalysisResultPtr ar) { if (!m_include.empty()) { if (ar->getPhase() == AnalysisResult::AnalyzeInclude) { ar->parseOnDemand(m_include); } else if (ar->getPhase() == AnalysisResult::AnalyzeAll) { analyzeInclude(ar, m_include); } } if (!getScope()->inPseudoMain() && !m_privateScope) { VariableTablePtr var = getScope()->getVariables(); var->setAttribute(VariableTable::ContainsLDynamicVariable); var->forceVariants(ar, VariableTable::AnyVars); } UnaryOpExpression::analyzeProgram(ar); }
void FunctionScope::RecordRefParamInfo(string fname, FunctionScopePtr func) { RefParamInfoPtr info = s_refParamInfo[fname]; if (!info) { info = RefParamInfoPtr(new RefParamInfo()); s_refParamInfo[fname] = info; } if (func->isReferenceVariableArgument()) { info->setRefVarArg(func->getMaxParamCount()); } VariableTablePtr variables = func->getVariables(); for (int i = 0; i < func->getMaxParamCount(); i++) { if (func->isRefParam(i)) info->setRefParam(i); variables->addParam(func->getParamName(i), TypePtr(), AnalysisResultPtr(), ConstructPtr()); } }
bool Expression::CheckNeeded(ExpressionPtr variable, ExpressionPtr value) { // if the value may involve object, consider the variable as "needed" // so that objects are not destructed prematurely. bool needed = true; if (value) needed = CheckNeededRHS(value); if (variable->is(Expression::KindOfSimpleVariable)) { auto var = dynamic_pointer_cast<SimpleVariable>(variable); const std::string &name = var->getName(); VariableTablePtr variables = var->getScope()->getVariables(); if (needed) { variables->addNeeded(name); } else { needed = variables->isNeeded(name); } } return needed; }
void ClassVariable::onParseRecur(AnalysisResultConstPtr ar, ClassScopePtr scope) { ModifierExpressionPtr modifiers = scope->setModifiers(m_modifiers); if (m_modifiers->isAbstract()) { parseTimeFatal(Compiler::InvalidAttribute, "Properties cannot be declared abstract"); } if (m_modifiers->isFinal()) { parseTimeFatal(Compiler::InvalidAttribute, "Properties cannot be declared final"); } for (int i = 0; i < m_declaration->getCount(); i++) { VariableTablePtr variables = scope->getVariables(); ExpressionPtr exp = (*m_declaration)[i]; if (exp->is(Expression::KindOfAssignmentExpression)) { AssignmentExpressionPtr assignment = dynamic_pointer_cast<AssignmentExpression>(exp); ExpressionPtr var = assignment->getVariable(); const std::string &name = dynamic_pointer_cast<SimpleVariable>(var)->getName(); if (variables->isPresent(name)) { exp->parseTimeFatal(Compiler::DeclaredVariableTwice, "Cannot redeclare %s::$%s", scope->getOriginalName().c_str(), name.c_str()); } else { assignment->onParseRecur(ar, scope); } } else { const std::string &name = dynamic_pointer_cast<SimpleVariable>(exp)->getName(); if (variables->isPresent(name)) { exp->parseTimeFatal(Compiler::DeclaredVariableTwice, "Cannot redeclare %s::$%s", scope->getOriginalName().c_str(), name.c_str()); } else { variables->add(name, Type::Null, false, ar, exp, m_modifiers); } } } scope->setModifiers(modifiers); }