96e793360b
It turned out a lot of the namespace stuff still worked. The biggest thing for the first pass is that we don't fallback to the global function or constant if there isn't a namespaced one. Also, when a constant has a ##\## anywhere in it it throw an error when it isn't defined, instead of assuming the string.
141 linhas
4.7 KiB
C++
141 linhas
4.7 KiB
C++
/*
|
|
+----------------------------------------------------------------------+
|
|
| HipHop for PHP |
|
|
+----------------------------------------------------------------------+
|
|
| Copyright (c) 2010- Facebook, Inc. (http://www.facebook.com) |
|
|
+----------------------------------------------------------------------+
|
|
| This source file is subject to version 3.01 of the PHP license, |
|
|
| that is bundled with this package in the file LICENSE, and is |
|
|
| available through the world-wide-web at the following url: |
|
|
| http://www.php.net/license/3_01.txt |
|
|
| If you did not receive a copy of the PHP license and are unable to |
|
|
| obtain it through the world-wide-web, please send a note to |
|
|
| license@php.net so we can mail you a copy immediately. |
|
|
+----------------------------------------------------------------------+
|
|
*/
|
|
|
|
#include <compiler/expression/dynamic_function_call.h>
|
|
#include <compiler/analysis/code_error.h>
|
|
#include <compiler/expression/expression_list.h>
|
|
#include <compiler/expression/scalar_expression.h>
|
|
#include <compiler/expression/simple_function_call.h>
|
|
#include <compiler/analysis/function_scope.h>
|
|
#include <compiler/analysis/class_scope.h>
|
|
#include <util/util.h>
|
|
#include <compiler/option.h>
|
|
#include <compiler/analysis/variable_table.h>
|
|
|
|
using namespace HPHP;
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// constructors/destructors
|
|
|
|
DynamicFunctionCall::DynamicFunctionCall
|
|
(EXPRESSION_CONSTRUCTOR_PARAMETERS,
|
|
ExpressionPtr name, ExpressionListPtr params, ExpressionPtr cls)
|
|
: FunctionCall(EXPRESSION_CONSTRUCTOR_PARAMETER_VALUES(DynamicFunctionCall),
|
|
name, "", false, params, cls) {
|
|
}
|
|
|
|
ExpressionPtr DynamicFunctionCall::clone() {
|
|
DynamicFunctionCallPtr exp(new DynamicFunctionCall(*this));
|
|
FunctionCall::deepCopy(exp);
|
|
return exp;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// parser functions
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// static analysis functions
|
|
|
|
void DynamicFunctionCall::analyzeProgram(AnalysisResultPtr ar) {
|
|
FunctionCall::analyzeProgram(ar);
|
|
if (ar->getPhase() >= AnalysisResult::AnalyzeAll) {
|
|
if (!m_className.empty()) {
|
|
resolveClass();
|
|
}
|
|
if (!m_class) {
|
|
addUserClass(ar, m_className);
|
|
}
|
|
if (m_params) {
|
|
m_params->markParams(canInvokeFewArgs());
|
|
}
|
|
|
|
if (!m_class && m_className.empty()) {
|
|
FunctionScopePtr fs = getFunctionScope();
|
|
VariableTablePtr vt = fs->getVariables();
|
|
vt->setAttribute(VariableTable::ContainsDynamicFunctionCall);
|
|
}
|
|
}
|
|
}
|
|
|
|
ExpressionPtr DynamicFunctionCall::preOptimize(AnalysisResultConstPtr ar) {
|
|
if (ExpressionPtr rep = FunctionCall::preOptimize(ar)) return rep;
|
|
|
|
if (m_nameExp->isScalar()) {
|
|
Variant v;
|
|
if (m_nameExp->getScalarValue(v) &&
|
|
v.isString()) {
|
|
string name = v.toString().c_str();
|
|
ExpressionPtr cls = m_class;
|
|
if (!cls && !m_className.empty()) {
|
|
cls = makeScalarExpression(ar, m_className);
|
|
}
|
|
return ExpressionPtr(NewSimpleFunctionCall(
|
|
getScope(), getLocation(),
|
|
name, false, m_params, cls));
|
|
}
|
|
}
|
|
return ExpressionPtr();
|
|
}
|
|
|
|
TypePtr DynamicFunctionCall::inferTypes(AnalysisResultPtr ar, TypePtr type,
|
|
bool coerce) {
|
|
reset();
|
|
ConstructPtr self = shared_from_this();
|
|
if (m_class) {
|
|
m_class->inferAndCheck(ar, Type::Any, false);
|
|
} else if (!m_className.empty()) {
|
|
ClassScopePtr cls = resolveClassWithChecks();
|
|
if (cls) {
|
|
m_classScope = cls;
|
|
}
|
|
}
|
|
|
|
m_nameExp->inferAndCheck(ar, Type::Some, false);
|
|
|
|
if (m_params) {
|
|
for (int i = 0; i < m_params->getCount(); i++) {
|
|
(*m_params)[i]->inferAndCheck(ar, Type::Variant, true);
|
|
}
|
|
}
|
|
return Type::Variant;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// code generation functions
|
|
void DynamicFunctionCall::outputPHP(CodeGenerator &cg, AnalysisResultPtr ar) {
|
|
if (m_class || !m_className.empty()) {
|
|
StaticClassName::outputPHP(cg, ar);
|
|
cg_printf("::");
|
|
m_nameExp->outputPHP(cg, ar);
|
|
} else {
|
|
const char *prefix = Option::IdPrefix.c_str();
|
|
if (cg.getOutput() == CodeGenerator::TrimmedPHP &&
|
|
cg.usingStream(CodeGenerator::PrimaryStream) &&
|
|
!m_nameExp->is(Expression::KindOfScalarExpression)) {
|
|
cg_printf("${%sdynamic_load($%stmp = (", prefix, prefix);
|
|
m_nameExp->outputPHP(cg, ar);
|
|
cg_printf("), '%stmp'", prefix);
|
|
cg_printf(")}");
|
|
} else {
|
|
m_nameExp->outputPHP(cg, ar);
|
|
}
|
|
}
|
|
|
|
cg_printf("(");
|
|
if (m_params) m_params->outputPHP(cg, ar);
|
|
cg_printf(")");
|
|
}
|