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 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"); }
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); } }
void ArrayElementExpression::outputCPPExistTest(CodeGenerator &cg, AnalysisResultPtr ar, int op) { switch (op) { case T_ISSET: cg_printf("isset("); break; case T_EMPTY: cg_printf("empty("); break; default: ASSERT(false); } if (m_global) { if (!m_globalName.empty()) { VariableTablePtr variables = getScope()->getVariables(); string name = variables->getGlobalVariableName(cg, ar, m_globalName); cg_printf("g->%s", name.c_str()); } else { cg_printf("((LVariableTable *)g)->get("); m_offset->outputCPP(cg, ar); cg_printf(")"); } } else { m_variable->outputCPP(cg, ar); cg_printf(", "); m_offset->outputCPP(cg, ar); ScalarExpressionPtr sc = dynamic_pointer_cast<ScalarExpression>(m_offset); if (sc) { if (sc->isLiteralString()) { String s(sc->getLiteralString()); int64 n; if (!s.get()->isStrictlyInteger(n)) { cg_printf(", true"); // skip toKey() at run time } } } } cg_printf(")"); }
void SimpleVariable::outputCPPImpl(CodeGenerator &cg, AnalysisResultPtr ar) { if (m_this) { ASSERT((getContext() & ObjectContext) == 0); if (hasContext(LValue)) { // LValue and not ObjectContext must be $this = or $this[..] = // Wrap with Variant to avoid compiler error cg_printf("Variant(GET_THIS())"); } else { cg_printf("GET_THIS()"); } } else if (m_superGlobal) { VariableTablePtr variables = ar->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 = ar->getScope()->getVariables()->getVariablePrefix(ar, m_name); cg_printf("%s%s", prefix, cg.formatLabel(m_name).c_str()); } }
void ArrayElementExpression::outputCPPImpl(CodeGenerator &cg, AnalysisResultPtr ar) { if (m_global) { if (!m_globalName.empty()) { VariableTablePtr variables = ar->getScope()->getVariables(); string name = variables->getGlobalVariableName(cg, ar, m_globalName); cg_printf("g->%s", name.c_str()); } else { cg_printf("get_variable_table()->get("); m_offset->outputCPP(cg, ar); cg_printf(")"); } } else { TypePtr type = m_variable->getActualType(); if (hasContext(UnsetContext)) { cg_printf("unsetLval("); m_variable->outputCPP(cg, ar); cg_printf(", "); } else { if (m_variable->is(Expression::KindOfScalarExpression) || (type && (type->isInteger() || type->is(Type::KindOfDouble) || type->is(Type::KindOfObject) || type->is(Type::KindOfBoolean)))) { cg_printf(type && type->is(Type::KindOfString) ? "((String)" : "((Variant)"); m_variable->outputCPP(cg, ar); cg_printf(")"); } else { m_variable->outputCPP(cg, ar); } } if (m_offset) { bool lvalAt = false; bool rvalAt = false; if (hasContext(UnsetContext)) { // do nothing } else if (m_context & InvokeArgument) { cg_printf(".refvalAt("); } else if (m_context & (LValue|RefValue)) { cg_printf(".lvalAt("); lvalAt = true; } else { cg_printf(".rvalAt("); rvalAt = true; } m_offset->outputCPP(cg, ar); if (!type || !type->is(Type::KindOfString)) { bool prehashed = false; ScalarExpressionPtr sc = dynamic_pointer_cast<ScalarExpression>(m_offset); if (sc) { int64 hash = sc->getHash(); if (hash >= 0) { cg_printf(", 0x%016llXLL", hash); prehashed = true; } } if (!prehashed) { cg_printf(", -1"); } if (rvalAt) { if (!hasContext(ExistContext)) { cg_printf(", true"); // raise undefined index error } else { cg_printf(", false"); } } else if (lvalAt) { if (hasContext(ObjectContext)) { // object target might not trigger an array copy cg_printf(", true"); } else { cg_printf(", false"); } } if (!hasContext(UnsetContext) && sc && sc->isLiteralString()) { String s(sc->getLiteralString()); int64 n; if (!s.get()->isStrictlyInteger(n)) { cg_printf(", true"); // skip toKey() at run time } } } cg_printf(")"); } else { cg_printf(".lvalAt()"); } } }
void ArrayElementExpression::outputCPPImpl(CodeGenerator &cg, AnalysisResultPtr ar) { if (m_global) { if (!m_globalName.empty()) { VariableTablePtr variables = getScope()->getVariables(); string name = variables->getGlobalVariableName(cg, ar, m_globalName); cg_printf("g->%s", name.c_str()); } else { cg_printf("((LVariableTable *)g)->get("); m_offset->outputCPP(cg, ar); cg_printf(")"); } } else { TypePtr type = m_variable->getActualType(); if (hasContext(UnsetContext)) { cg_printf("unsetLval("); m_variable->outputCPP(cg, ar); cg_printf(", "); } else { if (m_variable->is(Expression::KindOfScalarExpression) || (type && (type->isInteger() || type->is(Type::KindOfDouble) || type->is(Type::KindOfObject) || type->is(Type::KindOfBoolean)))) { cg_printf(type && type->is(Type::KindOfString) ? "((String)" : "((Variant)"); m_variable->outputCPP(cg, ar); cg_printf(")"); } else { TypePtr act; if (!m_variable->hasCPPTemp() && m_variable->getImplementedType() && type->is(Type::KindOfArray) && !Type::SameType(m_variable->getImplementedType(), type)) { act = type; type = m_variable->getImplementedType(); m_variable->setActualType(m_variable->getImplementedType()); } m_variable->outputCPP(cg, ar); if (act) { m_variable->setActualType(act); } } } if (m_offset) { bool lvalAt = false; bool rvalAt = false; bool byRef = false; bool arrRef = false; const char *sep = ", AccessFlags::"; if (hasContext(UnsetContext)) { // do nothing } else if (hasContext(InvokeArgument) && cg.callInfoTop() != -1) { cg_printf(".argvalAt(cit%d->isRef(%d), ", cg.callInfoTop(), m_argNum); } else if (m_context & (LValue|RefValue|DeepReference)) { cg_printf(".lvalAt("); lvalAt = true; } else { byRef = (m_context & AccessContext) && (!type || !type->is(Type::KindOfString)); arrRef = byRef && type && type->is(Type::KindOfArray); cg_printf(".rval%s%s(", arrRef || !byRef ? "At" : "", byRef ? "Ref" : ""); rvalAt = true; } m_offset->outputCPP(cg, ar); if (!type || !type->is(Type::KindOfString)) { if (rvalAt) { if (byRef && !arrRef) { const string &tmp = cg.getReferenceTemp(); cg_printf(", %s", tmp.empty() ? "Variant()" : tmp.c_str()); } if (!hasContext(ExistContext)) { cg_printf(", AccessFlags::Error"); // raise undefined index error sep = "_"; } } else if (lvalAt) { if (hasContext(AccessContext)) { // Dont copy the array if the element is an object, or // is referenced. // This is safe in AccessContext (the parent is an ArrayElement, // or an ObjectProperty) because applying [] to an object will // either invoke OffsetGet, or fatal, and modifications to a // referenced element would be reflected in all copies // of the array anyway. cg_printf(", AccessFlags::CheckExist"); sep = "_"; } } ScalarExpressionPtr sc = dynamic_pointer_cast<ScalarExpression>(m_offset); if (!hasContext(UnsetContext) && sc && sc->isLiteralString()) { String s(sc->getLiteralString()); int64 n; if (!s.get()->isStrictlyInteger(n)) { if (lvalAt || rvalAt) { cg_printf("%sKey", sep); } else { cg_printf(", true"); // skip toKey() at run time } } } } cg_printf(")"); } else { cg_printf(".lvalAt()"); } } }
void SimpleVariable::outputCPPImpl(CodeGenerator &cg, AnalysisResultPtr ar) { VariableTablePtr variables = getScope()->getVariables(); if (m_this) { ASSERT((getContext() & ObjectContext) == 0); if (hasContext(OprLValue) || hasContext(AssignmentLHS)) { cg_printf("throw_assign_this()"); return; } if (variables->getAttribute(VariableTable::ContainsLDynamicVariable)) { ASSERT(m_sym); const string &namePrefix = getNamePrefix(); cg_printf("%s%sthis", namePrefix.c_str(), variables->getVariablePrefix(m_sym)); } else if (hasContext(DeepOprLValue) || hasContext(DeepAssignmentLHS) || hasContext(LValue)) { // $this[] op= ...; or $this[] = ... cg_printf("Variant(GET_THIS())"); } else { ClassScopePtr cls = getOriginalClass(); if (!cls || cls->derivedByDynamic()) { cg_printf("Object(GET_THIS())"); } else { cg_printf("GET_THIS_TYPED(%s)", cls->getId().c_str()); } } } else if (m_superGlobal) { const string &name = variables->getGlobalVariableName(ar, m_name); cg_printf("g->%s", name.c_str()); } else if (m_globals) { cg_printf("get_global_array_wrapper()"); } else { ASSERT(m_sym); bool sw = false; if (m_sym->isShrinkWrapped() && m_context == Declaration) { ASSERT(!getFunctionScope()->isGenerator()); TypePtr type = m_sym->getFinalType(); type->outputCPPDecl(cg, ar, getScope()); sw = true; cg_printf(" "); } const string &prefix0 = getNamePrefix(); const char *prefix1 = variables->getVariablePrefix(m_sym); cg_printf("%s%s%s", prefix0.c_str(), prefix1, CodeGenerator::FormatLabel(m_name).c_str()); if (m_originalSym) { cg.printf(" /* %s */", m_originalSym->getName().c_str()); } if (sw) { TypePtr type = m_sym->getFinalType(); const char *initializer = type->getCPPInitializer(); if (initializer) { cg_printf(" = %s", initializer); } } } }
void ArrayElementExpression::outputCPPImpl(CodeGenerator &cg, AnalysisResultPtr ar) { if (m_global) { if (!m_globalName.empty()) { VariableTablePtr variables = getScope()->getVariables(); string name = variables->getGlobalVariableName(ar, m_globalName); cg_printf("g->%s", name.c_str()); } else { cg_printf("((LVariableTable *)g)->get("); m_offset->outputCPP(cg, ar); cg_printf(")"); } } else { TypePtr type = m_variable->getType(); if (hasContext(UnsetContext)) { cg_printf("unsetLval("); m_variable->outputCPP(cg, ar); cg_printf(", "); } else { if (m_variable->is(Expression::KindOfScalarExpression) || (type && (type->isInteger() || type->is(Type::KindOfDouble) || type->is(Type::KindOfObject) || type->is(Type::KindOfBoolean)))) { cg_printf(type && type->is(Type::KindOfString) ? "((String)" : "((Variant)"); m_variable->outputCPP(cg, ar); cg_printf(")"); } else { m_variable->outputCPP(cg, ar); } } if (m_offset) { bool lvalAt = false; bool rvalAt = false; bool byRef = false; bool arrRef = false; const char *sep = ", AccessFlags::"; bool isArrayType = type && type->is(Type::KindOfArray); bool isStringType = type && type->is(Type::KindOfString); bool isRealChainRoot = isChainRoot() && hasCPPCseTemp(); TypePtr t; bool hasCseStore = isRealChainRoot && GetCseTempInfo( ar, static_pointer_cast<Expression>(shared_from_this()), t); if (hasContext(UnsetContext)) { // do nothing } else if (hasContext(InvokeArgument) && cg.callInfoTop() != -1) { ASSERT(!isRealChainRoot); // TODO: handle this case cg_printf(".argvalAt(cit%d->isRef(%d), ", cg.callInfoTop(), m_argNum); } else if (m_context & (LValue|RefValue|DeepReference)) { // if we see an array access element in LValue context, the // type inference pass will never infer its type to be a string ASSERT(!isStringType); if (isRealChainRoot && !isArrayType) { // chain roots for non array types (variants) should call // lvalRef() cg_printf(".lvalRef("); } else { cg_printf(".lvalAt("); } lvalAt = true; } else { byRef = ((m_context & AccessContext) || isRealChainRoot) && !isStringType; arrRef = byRef && isArrayType; cg_printf(".rval%s%s(", arrRef || !byRef ? "At" : "", byRef ? "Ref" : ""); rvalAt = true; } m_offset->outputCPP(cg, ar); if (!isStringType) { if (rvalAt) { if (byRef && !arrRef) { string tmp; if (hasCseStore) { tmp = string(Option::CseTempStoragePrefix) + m_cppCseTemp; } else { tmp = cg.getReferenceTemp(); } cg_printf(", %s", tmp.empty() ? "Variant()" : tmp.c_str()); } if (!hasContext(ExistContext)) { cg_printf(", AccessFlags::Error"); // raise undefined index error sep = "_"; } } else if (lvalAt) { if (hasCseStore && !isArrayType) { cg_printf(", %s%s", Option::CseTempStoragePrefix, m_cppCseTemp.c_str()); } if (hasContext(AccessContext)) { // Dont copy the array if the element is an object, or // is referenced. // This is safe in AccessContext (the parent is an ArrayElement, // or an ObjectProperty) because applying [] to an object will // either invoke OffsetGet, or fatal, and modifications to a // referenced element would be reflected in all copies // of the array anyway. cg_printf(", AccessFlags::CheckExist"); sep = "_"; } } ScalarExpressionPtr sc = dynamic_pointer_cast<ScalarExpression>(m_offset); if (!hasContext(UnsetContext) && sc && sc->isLiteralString()) { String s(sc->getLiteralString()); int64 n; if (!s.get()->isStrictlyInteger(n)) { if (lvalAt || rvalAt) { cg_printf("%sKey", sep); } else { cg_printf(", true"); // skip toKey() at run time } } } } cg_printf(")"); } else { cg_printf(".lvalAt()"); } } }