3db2140e3e
Various perling.
357 linhas
12 KiB
C++
357 linhas
12 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. |
|
|
+----------------------------------------------------------------------+
|
|
*/
|
|
|
|
#ifndef incl_HPHP_VARIABLE_TABLE_H_
|
|
#define incl_HPHP_VARIABLE_TABLE_H_
|
|
|
|
#include <compiler/analysis/symbol_table.h>
|
|
#include <compiler/statement/statement.h>
|
|
#include <compiler/analysis/class_scope.h>
|
|
|
|
namespace HPHP {
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
DECLARE_BOOST_TYPES(ModifierExpression);
|
|
DECLARE_BOOST_TYPES(CodeError);
|
|
DECLARE_BOOST_TYPES(VariableTable);
|
|
DECLARE_BOOST_TYPES(Expression);
|
|
DECLARE_BOOST_TYPES(ClassScope);
|
|
DECLARE_BOOST_TYPES(FunctionScope);
|
|
|
|
/**
|
|
* These are the only places that a new variable can be declared:
|
|
*
|
|
* variable = expr|variable|new obj(...)
|
|
* static_var_list: T_STATIC T_VARIABLE = static_scalar,...
|
|
* class_variable_declaration: class { T_VARIABLE = static_scalar,...}
|
|
* T_LIST (variable, T_LIST(...), ...) = ...
|
|
* try {...} catch (T obj) {...}
|
|
* extract(name_value_pair)
|
|
*/
|
|
class VariableTable : public SymbolTable {
|
|
friend class AssignmentExpression;
|
|
public:
|
|
enum Attribute {
|
|
ContainsDynamicVariable = 1,
|
|
ContainsLDynamicVariable = ContainsDynamicVariable | 2,
|
|
ContainsExtract = 4,
|
|
ContainsCompact = 8,
|
|
InsideStaticStatement = 16,
|
|
InsideGlobalStatement = 32,
|
|
ForceGlobal = 64,
|
|
ContainsUnset = 128,
|
|
NeedGlobalPointer = 256,
|
|
ContainsDynamicStatic = 512,
|
|
ContainsGetDefinedVars = 1024,
|
|
ContainsDynamicFunctionCall = 2048,
|
|
};
|
|
|
|
enum JumpTableType {
|
|
JumpReturn,
|
|
JumpSet,
|
|
JumpInitialized,
|
|
JumpInitializedString,
|
|
JumpIndex,
|
|
JumpReturnString
|
|
};
|
|
|
|
enum JumpTableName {
|
|
JumpTableGlobalGetImpl,
|
|
JumpTableGlobalExists,
|
|
JumpTableGlobalGetIndex,
|
|
|
|
JumpTableLocalGetImpl,
|
|
JumpTableLocalExists,
|
|
};
|
|
|
|
enum AlteredVarClass {
|
|
NonPrivateNonStaticVars = 1,
|
|
NonPrivateStaticVars = 2,
|
|
PrivateNonStaticVars = 4,
|
|
PrivateStaticVars = 8,
|
|
|
|
AnyNonStaticVars = NonPrivateNonStaticVars | PrivateNonStaticVars,
|
|
AnyStaticVars = NonPrivateStaticVars | PrivateStaticVars,
|
|
AnyNonPrivateVars = NonPrivateNonStaticVars | NonPrivateStaticVars,
|
|
AnyPrivateVars = PrivateNonStaticVars | PrivateStaticVars,
|
|
|
|
AnyVars = AnyStaticVars | AnyNonStaticVars
|
|
};
|
|
|
|
static int GetVarClassMask(bool privates, bool statics) {
|
|
return (statics ? 2 : 1) << (privates ? 2 : 0);
|
|
}
|
|
|
|
static int GetVarClassMaskForSym(const Symbol *sym) {
|
|
return GetVarClassMask(sym->isPrivate(), sym->isStatic());
|
|
}
|
|
|
|
public:
|
|
VariableTable(BlockScope &blockScope);
|
|
|
|
/**
|
|
* Get/set attributes.
|
|
*/
|
|
void setAttribute(Attribute attr) { m_attribute |= attr;}
|
|
void clearAttribute(Attribute attr) { m_attribute &= ~attr;}
|
|
bool getAttribute(Attribute attr) const {
|
|
return (m_attribute & attr) == attr;
|
|
}
|
|
|
|
bool isParameter(const std::string &name) const;
|
|
bool isPublic(const std::string &name) const;
|
|
bool isProtected(const std::string &name) const;
|
|
bool isPrivate(const std::string &name) const;
|
|
bool isStatic(const std::string &name) const;
|
|
bool isGlobal(const std::string &name) const;
|
|
bool isSuperGlobal(const std::string &name) const;
|
|
bool isLocal(const std::string &name) const;
|
|
bool isLocal(const Symbol *sym) const;
|
|
bool isRedeclared(const std::string &name) const;
|
|
bool isLocalGlobal(const std::string &name) const;
|
|
bool isNestedStatic(const std::string &name) const;
|
|
bool isLvalParam(const std::string &name) const;
|
|
bool isUsed(const std::string &name) const;
|
|
bool isNeeded(const std::string &name) const;
|
|
|
|
bool needLocalCopy(const Symbol *sym) const;
|
|
bool needLocalCopy(const std::string &name) const;
|
|
bool needGlobalPointer() const;
|
|
bool isPseudoMainTable() const;
|
|
bool hasPrivate() const;
|
|
bool hasNonStaticPrivate() const;
|
|
bool hasStatic() const { return m_hasStatic; }
|
|
|
|
virtual bool isInherited(const std::string &name) const;
|
|
|
|
void getLocalVariableNames(std::vector<std::string> &syms) const;
|
|
|
|
/**
|
|
* Get all variable's names.
|
|
*/
|
|
void getNames(std::set<std::string> &names,
|
|
bool collectPrivate = true) const;
|
|
|
|
Symbol *addSymbol(const std::string &name) {
|
|
return genSymbol(name, false);
|
|
}
|
|
|
|
Symbol *addDeclaredSymbol(const std::string &name, ConstructPtr construct) {
|
|
return genSymbol(name, false, construct);
|
|
}
|
|
|
|
/**
|
|
* Add a function's parameter to this table.
|
|
*/
|
|
TypePtr addParam(const std::string &name, TypePtr type,
|
|
AnalysisResultConstPtr ar, ConstructPtr construct);
|
|
|
|
TypePtr addParamLike(const std::string &name, TypePtr type,
|
|
AnalysisResultPtr ar, ConstructPtr construct,
|
|
bool firstPass);
|
|
|
|
/**
|
|
* Called when a variable is declared or being assigned (l-value).
|
|
*/
|
|
TypePtr add(const std::string &name, TypePtr type, bool implicit,
|
|
AnalysisResultConstPtr ar, ConstructPtr construct,
|
|
ModifierExpressionPtr modifiers);
|
|
TypePtr add(Symbol *sym, TypePtr type, bool implicit,
|
|
AnalysisResultConstPtr ar, ConstructPtr construct,
|
|
ModifierExpressionPtr modifiers);
|
|
|
|
/**
|
|
* Called to note whether a class variable overrides
|
|
* a definition in a base class. Returns whether or not there
|
|
* was an error in marking as override.
|
|
*/
|
|
bool markOverride(AnalysisResultPtr ar, const std::string &name);
|
|
|
|
/**
|
|
* Called when a variable is used or being evaluated (r-value).
|
|
*/
|
|
TypePtr checkVariable(const std::string &name, TypePtr type, bool coerce,
|
|
AnalysisResultConstPtr ar, ConstructPtr construct);
|
|
TypePtr checkVariable(Symbol *sym, TypePtr type, bool coerce,
|
|
AnalysisResultConstPtr ar, ConstructPtr construct);
|
|
/**
|
|
* Find the class which contains the property, and return
|
|
* its Symbol
|
|
*/
|
|
Symbol *findProperty(ClassScopePtr &cls,
|
|
const std::string &name,
|
|
AnalysisResultConstPtr ar);
|
|
|
|
/**
|
|
* Caller is responsible for grabbing a lock on this class scope,
|
|
* This function will be responsible for grabbing (and releasing)
|
|
* a lock on the parent scope if necessary.
|
|
*/
|
|
TypePtr checkProperty(BlockScopeRawPtr context,
|
|
Symbol *sym, TypePtr type,
|
|
bool coerce, AnalysisResultConstPtr ar);
|
|
|
|
/**
|
|
* Walk up to find first parent that has the specified symbol.
|
|
*/
|
|
ClassScopePtr findParent(AnalysisResultConstPtr ar,
|
|
const std::string &name,
|
|
const Symbol *&sym) const;
|
|
|
|
ClassScopePtr findParent(AnalysisResultConstPtr ar,
|
|
const std::string &name,
|
|
Symbol *&sym) {
|
|
const Symbol *ss;
|
|
ClassScopePtr p = findParent(ar, name, ss); // const version
|
|
sym = const_cast<Symbol*>(ss);
|
|
return p;
|
|
}
|
|
|
|
/**
|
|
* Called when analyze global and static statement.
|
|
*/
|
|
bool checkRedeclared(const std::string &name, Statement::KindOf kindOf);
|
|
void addLocalGlobal(const std::string &name);
|
|
void addNestedStatic(const std::string &name);
|
|
|
|
/**
|
|
* Helper for static variable default value
|
|
*/
|
|
ConstructPtr getStaticInitVal(std::string varName);
|
|
bool setStaticInitVal(std::string varName, ConstructPtr value);
|
|
|
|
/**
|
|
* Helper for class variable default value
|
|
*/
|
|
ConstructPtr getClassInitVal(std::string varName);
|
|
bool setClassInitVal(std::string varName, ConstructPtr value);
|
|
|
|
/**
|
|
* Called when analyze simple variable
|
|
*/
|
|
void addLvalParam(const std::string &name);
|
|
void addUsed(const std::string &name);
|
|
bool checkUnused(Symbol *sym);
|
|
void addNeeded(const std::string &name);
|
|
void clearUsed();
|
|
void addStaticVariable(Symbol *sym, AnalysisResultConstPtr ar,
|
|
bool member = false);
|
|
void addStaticVariable(Symbol *sym, AnalysisResultPtr ar,
|
|
bool member = false);
|
|
void cleanupForError(AnalysisResultConstPtr ar);
|
|
|
|
/**
|
|
* Set all matching variables to variants, since l-dynamic value was used.
|
|
*/
|
|
void forceVariants(AnalysisResultConstPtr ar, int varClass,
|
|
bool recur = true);
|
|
|
|
/**
|
|
* Set one matching variable to be Type::Variant.
|
|
*/
|
|
void forceVariant(AnalysisResultConstPtr ar, const std::string &name,
|
|
int varClass);
|
|
|
|
/**
|
|
* Keep track of $GLOBALS['var'].
|
|
*/
|
|
void addSuperGlobal(const std::string &name);
|
|
bool isConvertibleSuperGlobal(const std::string &name) const;
|
|
|
|
/**
|
|
* Canonicalize symbol order of static globals.
|
|
*/
|
|
void canonicalizeStaticGlobals();
|
|
|
|
/**
|
|
* Generate all variable declarations for this symbol table.
|
|
*/
|
|
void outputPHP(CodeGenerator &cg, AnalysisResultPtr ar);
|
|
/**
|
|
* Whether or not the specified jump table is empty.
|
|
*/
|
|
bool hasAllJumpTables() const {
|
|
return m_emptyJumpTables.empty();
|
|
}
|
|
bool hasJumpTable(JumpTableName name) const {
|
|
return m_emptyJumpTables.find(name) == m_emptyJumpTables.end();
|
|
}
|
|
|
|
/**
|
|
* These are static variables collected from different local scopes,
|
|
* as they have to be turned into global variables defined in
|
|
* GlobalVariables class to make ThreadLocal<GlobalVaribles> work.
|
|
* This data structure is only needed by global scope.
|
|
*/
|
|
DECLARE_BOOST_TYPES(StaticGlobalInfo);
|
|
struct StaticGlobalInfo {
|
|
Symbol *sym;
|
|
VariableTable *variables; // where this variable was from
|
|
ClassScopeRawPtr cls; // these need to be raw to avoid reference cycles
|
|
FunctionScopeRawPtr func;
|
|
|
|
// get unique identifier for this variable
|
|
static std::string GetId(ClassScopePtr cls,
|
|
FunctionScopePtr func, const std::string &name);
|
|
};
|
|
|
|
bool hasStaticLocals() const { return !m_staticLocalsVec.empty(); }
|
|
|
|
private:
|
|
enum StaticSelection {
|
|
NonStatic = 1,
|
|
Static = 2,
|
|
EitherStatic = 3
|
|
};
|
|
|
|
enum PrivateSelection {
|
|
NonPrivate = 1,
|
|
Private = 2,
|
|
EitherPrivate = 3
|
|
};
|
|
|
|
int m_attribute;
|
|
int m_nextParam;
|
|
unsigned m_hasGlobal : 1;
|
|
unsigned m_hasStatic : 1;
|
|
unsigned m_hasPrivate : 1;
|
|
unsigned m_hasNonStaticPrivate : 1;
|
|
unsigned m_forcedVariants : 4;
|
|
|
|
std::set<JumpTableName> m_emptyJumpTables;
|
|
|
|
StaticGlobalInfoPtrVec m_staticGlobalsVec;
|
|
StringToStaticGlobalInfoPtrMap m_staticGlobals;
|
|
|
|
/** static symbols local to this variable table (ie for closures) */
|
|
SymbolVec m_staticLocalsVec;
|
|
|
|
bool isGlobalTable(AnalysisResultConstPtr ar) const;
|
|
|
|
virtual TypePtr setType(AnalysisResultConstPtr ar, const std::string &name,
|
|
TypePtr type, bool coerce);
|
|
virtual TypePtr setType(AnalysisResultConstPtr ar, Symbol *sym,
|
|
TypePtr type, bool coerce);
|
|
virtual void dumpStats(std::map<std::string, int> &typeCounts);
|
|
|
|
void checkSystemGVOrder(SymbolSet &variants, unsigned int max);
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
}
|
|
|
|
#endif // incl_HPHP_VARIABLE_TABLE_H_
|