下面主要分析的是优化阶段和推导阶段的分析,前优化和后优化类似,所以就不具体再分析后优化;
1. preOptimize分析
1.1. preOptimize作用
1.将可以进行计算和拼接的简单的一元、二元表达式进行计算和拼接返回成为一个ScalarExpression(但变量和变量之间的是不能在preOptimize中进行合并的,这样的需要进行类型推导后才可以进行优化)
如:
$a=1+2*3+4 优化后$a=11
$a=“123”+3 优化后$a =126
$b=2;$a=$b+3 ; 优化后$a=5;
$a=“a”.”b”.”c” 优化后 $a=“abc”
2.多个连接语句进行字符串拼接
如:
$a.=“aa”;
$b=“bb”;
$a.=$b.“dd”;
优化后 $a=“aa”.”bb”.”dd”;数组优化同理
3.优化后的表达式,封装到上一级的表达式或者语句中,将语法树进行简化
1.2. preOptimize 处理流程
1.3. preOptimize 实例
例:$a=1+2*3+4
语法树:
(1)优化2*3 返回结果ScalarExpression(6),封装到上一级的BinaryOpExpression上
(2)优化1+6返回结果ScalarExpression(7),封装到上一级的BinaryOpExpression上
(3)优化1+6返回结果ScalarExpression(11),封装到上一级的AssignmentExpression上,最终把一颗大树优化为了一个赋值表达式
1.4. preOptimize代码分析
这里抽取一个一元表达式的作为例子进行分析(unary_op_expression.cpp):
/*
解析一元表达式,并进行计算,计算出结果(reslut),然后返回
一个scalarExpr(result),表达式;
如果m_exp是一元或者二元表达式则返回原表达式;
*/
ExpressionPtr UnaryOpExpression::preOptimize(AnalysisResultConstPtr ar) {
Variant value;
Variant result;
if (m_exp && ar->getPhase() >= AnalysisResult::FirstPreOptimize) {
//T_UNSET : unset
if (m_op == T_UNSET) {
if (m_exp->isScalar() ||
(m_exp->is(KindOfExpressionList) &&
static_pointer_cast<ExpressionList>(m_exp)->getCount() == 0)) {
recomputeEffects();
//返回一个null
return CONSTANT("null");
}
return ExpressionPtr();
}
}
//T_ISSET :isset
if (m_op == T_ISSET && m_exp->is(KindOfExpressionList) &&
static_pointer_cast<ExpressionList>(m_exp)->getListKind() ==
ExpressionList::ListKindParam) {
ExpressionListPtr el(static_pointer_cast<ExpressionList>(m_exp));
result = true;
int i = 0, n = el->getCount();
for (; i < n; i++) {
//根据下标获取el列表下的expr
ExpressionPtr e((*el)[i]);
//如果e为空或e类型不是scalar 则break;
if (!e || !e->isScalar() || !e->getScalarValue(value)) break;
if (!isset(value)) {
result = false;
}
}
//遍历完最后一个expr时,然后返回一个result值,并且将作用域和类型保持与当前表达式一致
if (i == n) {
return replaceValue(makeScalarExpression(ar, result));
}
} else if (m_op != T_ARRAY &&
m_exp &&
m_exp->isScalar() &&
m_exp->getScalarValue(value) &&
preCompute(value, result)) {
//非array ,并且m_exp不为空,m_exp是scalar类型, 调用preCompute返回计算后的result值
//返回result的scalar表达式,并且修改作用域和类型与当前表达式一致
return replaceValue(makeScalarExpression(ar, result));
} else if (m_op == T_BOOL_CAST) {
switch (m_exp->getKindOf()) {
default: break;
//表达式类型为KindOfBinaryOpExpression
case KindOfBinaryOpExpression: {
//获取操作符
int op = static_pointer_cast<BinaryOpExpression>(m_exp)->getOp();
switch (op) {
//OR
case T_LOGICAL_OR:
//||
case T_BOOLEAN_OR:
//AND
case T_LOGICAL_AND:
//&&
case T_BOOLEAN_AND:
//XOR
case T_LOGICAL_XOR:
//instanceof
case T_INSTANCEOF:
case '<':
//<=
case T_IS_SMALLER_OR_EQUAL:
case '>':
//>=
case T_IS_GREATER_OR_EQUAL:
//===
case T_IS_IDENTICAL:
//!==
case T_IS_NOT_IDENTICAL:
//==
case T_IS_EQUAL:
//!= <>
case T_IS_NOT_EQUAL:
//返回这个二元表达式
return m_exp;
}
break;
}
//m_exp是个一元表达式
case KindOfUnaryOpExpression: {
int op = static_pointer_cast<UnaryOpExpression>(m_exp)->getOp();
switch (op) {
//bool|boolean
case T_BOOL_CAST:
case '!':
//isset
case T_ISSET:
//empty
case T_EMPTY:
//print
case T_PRINT:
//返回当前一元表达式
return m_exp;
}
break;
}
}
}
return ExpressionPtr();
}
2. inferType分析
2.1. inferType的作用
Infertype的主要作用是在pre-optimize的基础之上进行类型推衍,对表达式的类型、变量的类型进行推衍。并判断类型是否和上下文所期望的一致。形如$a = $b + $c ;这种形式,类型推衍将$b和$c的类型推衍成同一类型的然后再进行操作(post-optimize)。
Infertype的最基本操作包括BinaryOpExpression、AssignmentExpression、UnaryOpExpression。
2.2. inferType的流程
1)根据functionscope对文件进行划分
2)获取functionscope下的statementlist,对statementlist进行遍历获取到每条statement。
3)对statement中的expression进行类型推衍,通过调用inferTypes(ar, type, coerce);方法分析出当前的expression是哪一种( AssignmentExpression 、scalarexpression等),在通过inferAndCheck()方法对表达式进行推衍和检查,最终得到表达式的类型。
4)将分析出的最小表达式的类型返回到上一级再次进行分析,直到分析出expression或者statement的类型。
下面有3个expression中的infertype的3个关键函数的实现分析:
inferAndCheck,checkTypesImpl,setTypes;
这3个函数的关系为:inferAndCheck=> checkTypesImpl=> setTypes
inferAndCheck 推导和检查类型(检查类型实现是checkTypesImpl,设置最终类型是setTypes);
以下是3个函数的实现具体的代码分析,在expression.cpp中:
2.2.1. inferAndCheck:
/*
coerce是否强制转换
*/
TypePtr Expression::inferAndCheck(AnalysisResultPtr ar, TypePtr type,
bool coerce) {
IMPLEMENT_INFER_AND_CHECK_ASSERT(getScope());
ASSERT(type);
resetTypes();
//获取实际类型
TypePtr actualType = inferTypes(ar, type, coerce);
//通过传入的type判断是执行如下语句还是执行checkTypesImpl
if (type->is(Type::KindOfSome) || type->is(Type::KindOfAny)) {
m_actualType = actualType;
m_expectedType.reset();
return actualType;
}
//返回期望值
return checkTypesImpl(ar, type, actualType, coerce);
}
2.2.2. checkTypesImpl:
TypePtr Expression::checkTypesImpl(AnalysisResultConstPtr ar,
TypePtr expectedType,
TypePtr actualType, bool coerce) {
TypePtr ret;
//返回实际类型
actualType = propagateTypes(ar, actualType);
ASSERT(actualType);
//是否强转
if (coerce) {
ret = Type::Coerce(ar, expectedType, actualType);
//设置实际和期望类型
setTypes(ar, actualType, expectedType);
} else {
//返回期望类型,返回交集
ret = Type::Intersection(ar, actualType, expectedType);
setTypes(ar, actualType, ret);
}
ASSERT(ret);
return ret;
}
2.2.3. setTypes:
//设置当前表达式的类型
//设置m_actualType 和m_expectedType
void Expression::setTypes(AnalysisResultConstPtr ar, TypePtr actualType,
TypePtr expectedType) {
ASSERT(actualType);
ASSERT(expectedType);
m_actualType = actualType;
//如果expectedType非any和some类型,那么将expectedType设置为期望类型,否则清空m_expectedType
if (!expectedType->is(Type::KindOfAny) &&
!expectedType->is(Type::KindOfSome)) {
// store the expected type if it is not Any nor Some,
// regardless of the actual type
m_expectedType = expectedType;
} else {
m_expectedType.reset();
}
// This is a special case where Type::KindOfObject means any object.
//m_expectedType是一个对象类型,并不是一个特殊对象时(如m_name=a,也就是class A,这是一个特殊对象)
//并且实际类型是一个特殊对象
if (m_expectedType && m_expectedType->is(Type::KindOfObject) &&
!m_expectedType->isSpecificObject() &&
m_actualType->isSpecificObject()) {
m_expectedType.reset();
}
//如果m_actualType 是一个特殊对象,那么将它添加到文件作用域的依赖中
if (m_actualType->isSpecificObject()) {
boost::const_pointer_cast<AnalysisResult>(ar)->
addClassDependency(getFileScope(), m_actualType->getName());
}
}
2.3. inferType原理
强转Type::Coerce
秉持的思想是向大的类型转,存在以下几种类型:
①当有一种类型为KindOfVariant 那么返回Type::Variant。
②当type1为KindOfVoid ,type2为KindOfString、 KindOfArray、 KindOfObject返回type2的类型
③当type1为某一具体类型,type2为KindOfSome、 KindOfAny返回type1的类型
④当type1为KindOfString, type2为KindOfArray返回Type:: Sequence。
⑤当type1唯一确定为KindOfInteger,如果type2唯一确定为KindOfInteger,返回type2,否则如果type2唯一确定为KindOfDouble,返回Type::Numeric。
⑥当type为objcet返回父类。
如下都是类型推导的具体的代码分析:
Coerce是强转类型,实际类型和期望类型之间进行转换;
Intersection 取交集类型;
IsLegalCast判断2种类型是否一致;
isStandardObject 判断是否Object类型;
isSpecificObject 是否是特定的类型,如自定义类class A这样的类型;
isNonConvertibleType 是否是Object或者Array 的类型;
isNoObjectInvolved 判断是否是非对象类型(如果是Object或者Array,则返回false)
InferredObject 推导多态的返回类型;
Inferred 推导类型;
combinedArithmeticType 数字类型推导;
php转换cpp的输出内容;
2.3.1. Type::Coerce(强转类型)
强转的函数在type.cpp中,Type::Coerce,代码如下:
//强制转换 type1是期望类型 type2 是实际类型
TypePtr Type::Coerce(AnalysisResultConstPtr ar, TypePtr type1, TypePtr type2) {
//type1和type2相同返回type1
if (SameType(type1, type2)) return type1;
//type1或type2是variant返回variant
if (type1->m_kindOf == KindOfVariant ||
type2->m_kindOf == KindOfVariant) return Type::Variant;
//如果type1 包含了type2 则将type1 和type2 互换,保证type1是子集
if (type1->m_kindOf > type2->m_kindOf) {
TypePtr tmp = type1;
type1 = type2;
type2 = tmp;
}
//type1是void ,type2是string array object,那么返回type2
if (type1->m_kindOf == KindOfVoid &&
(type2->m_kindOf == KindOfString ||
type2->m_kindOf == KindOfArray ||
type2->m_kindOf == KindOfObject)) {
return type2;
}
//type2是some any返回type1
if (type2->m_kindOf == KindOfSome ||
type2->m_kindOf == KindOfAny) return type1;
//
if (type2->m_kindOf & KindOfAuto) {
//type1 必须是type2不包含auto类型
if (type1->mustBe(type2->m_kindOf & ~KindOfAuto)) {
//type1不是string ,返回type1
if (!(type1->m_kindOf & Type::KindOfString)) {
return type1;
}
if (type2->m_kindOf == KindOfAutoSequence) {
return Type::Sequence;
}
//获取type2类型,清除auto
return GetType((KindOf)(type2->m_kindOf & ~KindOfAuto));
}
return Type::Variant;
}
// type1 type2都是integer,返回type2
//type1 是integer,type2是double 返回Numeric
if (type1->mustBe(KindOfInteger)) {
if (type2->mustBe(KindOfInteger)) {
return type2;
} else if (type2->mustBe(KindOfDouble)) {
return Type::Numeric;
}
}
//type1 和type2必须是object
if (type1->mustBe(Type::KindOfObject) &&
type2->mustBe(Type::KindOfObject)) {
//type1和type2名字为空返回本身
if (type1->m_name.empty()) return type1;
if (type2->m_name.empty()) return type2;
//根据名字查找类并返回type
ClassScopePtr cls1 = ar->findClass(type1->m_name);
//cls1不重复,并且type2是他的父类,返回type2
if (cls1 && !cls1->isRedeclaring() &&
cls1->derivesFrom(ar, type2->m_name, true, false)) {
return type2;
}
//cls2不重复,并且type1是他的父类,返回type1
ClassScopePtr cls2 = ar->findClass(type2->m_name);
if (cls2 && !cls2->isRedeclaring() &&
cls2->derivesFrom(ar, type1->m_name, true, false)) {
return type1;
}
//cls1 和cls2存在并且都不重复查找cls1或cls2的父类,并且返回
if (cls1 && cls2 &&
!cls1->isRedeclaring() && !cls2->isRedeclaring()) {
//返回父类
ClassScopePtr parent =
ClassScope::FindCommonParent(ar, type1->m_name,
type2->m_name);
if (parent) {
//创建父类的类型对象
return Type::CreateObjectType(parent->getName());
}
}
return Type::Object;
}
if (type1->mustBe(type2->m_kindOf)) {
return type2;
}
CT_ASSERT(Type::KindOfString < Type::KindOfArray);
if (type1->m_kindOf == Type::KindOfString &&
type2->m_kindOf == Type::KindOfArray) {
return Type::Sequence;
}
return Type::Variant;
}
2.3.2. Type::Intersection(取交集)
TypePtr Type::Intersection(AnalysisResultConstPtr ar,
TypePtr from, TypePtr to) {
// Special case: if we're casting to Some or Any, return the "from" type;
// if we're casting to Variant, return Variant.
//to 一般为期望值from一般为实际类型
//to为some或any时,返回from
if (to->m_kindOf == KindOfSome || to->m_kindOf == KindOfAny) {
return from;
} else if (to->m_kindOf == KindOfVariant) {
return Variant;
}
//获取to和from的类型交际
int resultKind = to->m_kindOf & from->m_kindOf;
std::string resultName = "";
//交集为object
if (resultKind & KindOfObject) {
// if they're the same, or we don't know one's name, then use
// the other
//to 和from的类型名字一致或者from 名字为空,resultName为to的名字
if (to->m_name == from->m_name || from->m_name.empty()) {
resultName = to->m_name;
} else if (to->m_name.empty()) {
//to 的名字为空,resultName为from的名字
resultName = from->m_name;
} else {
// make sure there's a subclass relation
//查找from的类
ClassScopePtr cls = ar->findClass(from->m_name);
if (cls) {
//判断to是否是from 的父类,如果是resultName设置为to的名字
if (cls->derivesFrom(ar, to->m_name, true, false)) {
resultName = to->m_name;
} else {
//不是则清空resultKind的KindOfObject类型
resultKind &= ~KindOfObject;
}
}
}
}
TypePtr res;
// If there is overlap (for instance, they were the same, or we've narrowed
// down something like Sequenece to be more specific), then return the
// intersection of the types.
if (resultKind) {
//根据类型名称返回类型
res = GetType(resultKind, resultName);
} else if (from->mustBe(KindOfObject) && to->m_kindOf == KindOfPrimitive) {
//from必须为对象类型,并且to的类型必须是string 或KindOfNumeric(不存在交集)
// Special case Object -> Primitive: can we tostring it?
//from名字不为空
if (!from->m_name.empty()) {
//查找from的类,查找__tostring方法如果存在则返回ret为string
ClassScopePtr cls = ar->findClass(from->m_name);
if (cls && cls->findFunction(ar, "__tostring", true)) {
res = Type::String;
}
}
// Otherwise, return Int32
res = Int32;
} else if (from->m_kindOf == KindOfBoolean
&& to->mustBe(KindOfNumeric | KindOfArray | KindOfString)
&& !IsExactType(to->m_kindOf)) {
res = Int32;
} else {
res = to;
}
//from 是boolean ,to是string 和KindOfNumeric 返回int32
if (from->mustBe(KindOfBoolean) && to->m_kindOf == KindOfPrimitive) {
res = Int32;
}
return res;
}
2.3.3. Type::IsLegalCast
/* This new IsLegalCast returns true in a few cases where the old version
* (which was basically a hardcoded truth table) returned false; it seems
* like "true" is in fact the right thing to return. The cases that appear
* when compiling www are:
* Sequence -> Array
* PlusOperand -> Array
* String -> PlusOperand
* Boolean -> PlusOperand
*/
//对比to和from类型是否相同
bool Type::IsLegalCast(AnalysisResultConstPtr ar, TypePtr from, TypePtr to) {
if (!from->m_kindOf) return true;
// since both 'from' and 'to' represent sets of types, we do
// this by computing the set of types that we could possibly cast 'from'
// to, and then determining whether that overlaps with 'to'.
//给canCastTo加上boolean类型
int canCastTo = KindOfBoolean | from->m_kindOf;
//判断from类型中是否有void,如果存在则canCastTo加上void
if (from->m_kindOf & KindOfVoid) canCastTo |= KindOfVoid;
// Boolean, Numeric, and String can all be cast among each other
//判断from中是否有boolean ,数字型和字符串,如果存在给canCastTo加上数字型和字符串
if (from->m_kindOf & (KindOfBoolean | KindOfNumeric | KindOfString)) {
canCastTo |= KindOfNumeric | KindOfString;
}
//判断from是否有对象型
if (from->m_kindOf & KindOfObject) {
// Objects can only cast to string if they have __tostring
//名字为空,添加上string性
if (from->m_name.empty()) {
canCastTo |= KindOfString; // we don't know which class it is
} else {
//否则是类的对象类型,通过from名字查询cls
ClassScopePtr cls = ar->findClass(from->m_name);
if (!cls || cls->isRedeclaring() ||
cls->findFunction(ar, "__tostring", true)) {
canCastTo |= KindOfString;
}
}
// can only cast between objects if there's a subclass relation
//to 的类型包含object并且类型名字不为空,
//并且from类型名字不为空,并且to的m_name不等于from的m_name
if ((to->m_kindOf & KindOfObject) && !to->m_name.empty() &&
!from->m_name.empty() && to->m_name != from->m_name) {
//查找类
ClassScopePtr cls = ar->findClass(from->m_name);
//类存在,并且类是重复的,将canCastTo的对象类型删除
if (cls && (cls->isRedeclaring() ||
!cls->derivesFrom(ar, to->m_name, true, true))) {
canCastTo &= ~KindOfObject;
}
}
}
//判断to 的类型是否在canCastTo中
bool overlap = (to->m_kindOf & canCastTo);
return overlap;
}
2.3.4. Type::isStandardObject()
//标准的Object,不是特定的class类
bool Type::isStandardObject() const {
return m_kindOf == KindOfObject && m_name.empty();
}
2.3.5. Type::isSpecificObject()
//特殊的对象,kindof类型并且名字不为空,如class A ,这样类的类型就是
bool Type::isSpecificObject() const {
return m_kindOf == KindOfObject && !m_name.empty();
}
2.3.6. Type::isNonConvertibleType()
bool Type::isNonConvertibleType() const {
return m_kindOf == KindOfObject || m_kindOf == KindOfArray;
}
2.3.7. Type::isNoObjectInvolved()
//判断不是一个对象,如果为array或object则返回false
bool Type::isNoObjectInvolved() const {
if (couldBe(KindOfObject)
|| couldBe(KindOfArray))
return false;
else
return true;
}
2.3.8. Type::InferredObject
//推导2个类的类型中返回类型
TypePtr Type::InferredObject(AnalysisResultConstPtr ar,
TypePtr type1,
TypePtr type2) {
ASSERT(type1->m_kindOf == KindOfObject);
ASSERT(type2->m_kindOf == KindOfObject);
TypePtr resultType = Type::Object;
// if they're the same, or we don't know one's name, then use
// the other
//type1和type2的类型名字相等或者type1的名字为空
if (type1->m_name == type2->m_name || type1->m_name.empty()) {
//赋值resultType的类型为type2
resultType = type2;
} else if (type2->m_name.empty()) {
//type2类型名为空,将resultType的类型设置为type1
resultType = type1;
} else {
// take the subclass
//获取2个类型的类
ClassScopePtr cls1 = ar->findClass(type1->m_name);
ClassScopePtr cls2 = ar->findClass(type2->m_name);
bool c1ok = cls1 && !cls1->isRedeclaring();
bool c2ok = cls2 && !cls2->isRedeclaring();
if (c1ok && cls1->derivesFrom(ar, type2->m_name, true, false)) {
resultType = type1;
} else if (c2ok && cls2->derivesFrom(ar, type1->m_name, true, false)) {
resultType = type2;
} else if (c1ok && c2ok && cls1->derivedByDynamic() &&
cls2->derivesFromRedeclaring()) {
resultType = type2;
} else {
resultType = type1;
}
}
return resultType;
}
2.3.9. Type::Inferred
/* We have inferred type1 and type2 as the actual types for the same
expression.
Check that the types are compatible (it cant be both a string and
an integer, for example), and return the combined type. If they
are not compatible, return a null pointer.
*/
//判断2个类型是否一致
TypePtr Type::Inferred(AnalysisResultConstPtr ar,
TypePtr type1, TypePtr type2) {
//判断type1或type2如果其中一个为空,返回另一个类型
if (!type1) return type2;
if (!type2) return type1;
KindOf k1 = type1->m_kindOf;
KindOf k2 = type2->m_kindOf;
if (k1 == k2) {
//k1 是object类型则返回推导类
return k1 == KindOfObject ?
Type:::InferredObject(ar, type1, type2) : type1;
}
// If one set is a subset of the other, return the subset.
/*判断k1和k2谁是另一个类型的子集返回
例k1 1111 k2 1011 ,那么k2是子集,k1包含k2,返回k2
*/
if ((k1 & k2) == k1) return type1;
if ((k1 & k2) == k2) return type2;
// If one type must be numeric and the other might be, then assume numeric
//type1 或type2中必须有一个是KindOfNumeric类型,并且另一个包含KindOfNumeric类型则返回某个type
if (type1->mustBe(KindOfNumeric) && type2->couldBe(KindOfNumeric)) {
return type1;
}
if (type2->mustBe(KindOfNumeric) && type1->couldBe(KindOfNumeric)) {
return type2;
}
// Otherwise, take the intersection
//如果是对象的返回对象类型
int resultKind = type1->m_kindOf & type2->m_kindOf;
if (resultKind == KindOfObject) {
return Type::InferredObject(ar, type1, type2);
}
return resultKind ? GetType(resultKind) : TypePtr();
}
2.3.10. Type::combinedArithmeticType
//数字运算的类型
/*
t1 是Primitive,如果t2也是,如果t2>t1 返回t2否则t1;
t1如果是double返回double否则是Numeric
t2如果是double返回double否则是Numeric
t1 或t2是Numeric 返回Numeric
如果kind小于KindOfInt64 ,返回KindOfInt64
否则都不符合返回空
*/
TypePtr Type::combinedArithmeticType(TypePtr t1, TypePtr t2) {
KindOf kind = KindOfAny;
//判断是否是array类型,是则返回空
if (t1 && t1->is(Type::KindOfArray) ||
t2 && t2->is(Type::KindOfArray)) {
return TypePtr();
}
//Primitive是Numeric 和String的集合;
//Numeric 是Double 和Integer的集合;
//type1 是Primitive
if (t1 && t1->isPrimitive()) {
//t2也是Primitive
if (t2 && t2->isPrimitive()) {
//t2大于t1,返回t2 否则t1
/*
例: t2:variant t1:int32 ,那么返回Variant
*/
if (t2->getKindOf() > t1->getKindOf()) {
kind = t2->getKindOf();
} else {
kind = t1->getKindOf();
}
} else if (t1->is(KindOfDouble)) {//t1是double返回double
kind = KindOfDouble;
} else {//否则返回Numeric
kind = KindOfNumeric;
}
} else if (t2 && t2->isPrimitive()) {
if (t2->is(KindOfDouble)) {
kind = KindOfDouble;
} else {
kind = KindOfNumeric;
}
} else if ((t1 && t1->mustBe(KindOfNumeric)) ||
(t2 && t2->mustBe(KindOfNumeric))) {
kind = KindOfNumeric;
}
if (kind < KindOfInt64) {
kind = KindOfInt64;
}
if (kind != KindOfAny) {
return GetType(kind);
}
return TypePtr();
}
2.3.11. 输出cpp的类型转换的推导
2.3.11.1. Type::getCPPDecl
/* 获取c++ 的输出类型*/
string Type::getCPPDecl(AnalysisResultConstPtr ar,
BlockScopeRawPtr scope,
CodeGenerator *cg /* = 0 */) {
switch (m_kindOf) {
case KindOfBoolean: return "bool";
case KindOfInt32: return "int";
case KindOfInt64: return "int64";
case KindOfDouble: return "double";
case KindOfString: return "String";
case KindOfArray: return "Array";
case KindOfObject:{
ClassScopePtr cls(getClass(ar, scope));
if (!cls) return "Object";
if (cg && cg->isFileOrClassHeader() && scope) {
if (scope->getContainingClass()) {
scope->getContainingClass()->addUsedClassHeader(cls);
} else if (scope->getContainingFile()) {
scope->getContainingFile()->addUsedClassHeader(cls);
}
}
//Option::SmartPtrPrefix=> p_ 返回值为p_类名
return Option::SmartPtrPrefix + cls->getId();
}
case KindOfNumeric: return "Numeric";
case KindOfPrimitive: return "Primitive";
case KindOfPlusOperand: return "PlusOperand";
case KindOfSequence: return "Sequence";
default:
return "Variant";
}
}
2.3.11.2. Type::getDataType()
获取数据类型的函数
DataType Type::getDataType() const {
switch (m_kindOf) {
case KindOfBoolean: return HPHP::KindOfBoolean;
case KindOfInt32:
case KindOfInt64: return HPHP::KindOfInt64;
case KindOfDouble: return HPHP::KindOfDouble;
case KindOfString: return HPHP::KindOfString;
case KindOfArray: return HPHP::KindOfArray;
case KindOfObject: return HPHP::KindOfObject;
case KindOfNumeric:
case KindOfPrimitive:
case KindOfPlusOperand:
case KindOfSequence:
default: return HPHP::KindOfUnknown;
}
}
2.3.11.3. Type::outputCPPDecl
//cpp输出声明类型
void Type::outputCPPDecl(CodeGenerator &cg, AnalysisResultConstPtr ar,
BlockScopeRawPtr scope) {
cg_printf(getCPPDecl(ar, scope, &cg).c_str());
}
2.3.11.4. Type::outputCPPFastObjectCast
/*
Php对象输出cpp类对象 p_类名
*/
void Type::outputCPPFastObjectCast(CodeGenerator &cg,
AnalysisResultConstPtr ar,
BlockScopeRawPtr scope,
bool isConst) {
ASSERT(isSpecificObject());
ClassScopePtr cls(getClass(ar, scope));
ASSERT(cls);
const string &cppClsName = cls->getId();
/*
Option::SmartPtrPrefix const p_类名
*/
cg_printf("(%s%s%s&)",
isConst ? "const " : "",
Option::SmartPtrPrefix,
cppClsName.c_str());
}
2.3.11.5. Type::outputCPPCast
/*
Php对应cpp 输出相应类型
*/
void Type::outputCPPCast(CodeGenerator &cg, AnalysisResultConstPtr ar,
BlockScopeRawPtr scope) {
switch (m_kindOf) {
case KindOfBoolean: cg_printf("toBoolean"); break;
case KindOfInt32: cg_printf("toInt32"); break;
case KindOfInt64: cg_printf("toInt64"); break;
case KindOfDouble: cg_printf("toDouble"); break;
case KindOfString: cg_printf("toString"); break;
case KindOfArray: cg_printf("toArray"); break;
case KindOfNumeric: cg_printf("Numeric"); break;
case KindOfPrimitive: cg_printf("Primitive"); break;
case KindOfPlusOperand: cg_printf("PlusOperand"); break;
case KindOfSequence: cg_printf("Sequence"); break;
case KindOfObject: {
ClassScopePtr cls(getClass(ar, scope));
if (!cls) {
cg_printf("toObject");
} else {
cg_printf("%s%s", Option::SmartPtrPrefix, cls->getId().c_str());
}
break;
}
default:
cg_printf("Variant");
break;
}
}
2.3.11.6. Type::getCPPInitializer()
//cpp 类型初始化内容
const char *Type::getCPPInitializer() {
switch (m_kindOf) {
case KindOfBoolean: return "false";
case KindOfInt32:
case KindOfInt64: return "0";
case KindOfNumeric:
case KindOfPrimitive:
case KindOfPlusOperand: return "0";
case KindOfDouble: return "0.0";
default: return NULL;
}
}
2.3.12. 类型推导的类型
类型在type.h中,有如下的类型:
static const KindOf KindOfVoid = 0x0001;
static const KindOf KindOfBoolean = 0x0002;
static const KindOf KindOfInt32 = 0x0010;
static const KindOf KindOfInt64 = 0x0020;
static const KindOf KindOfDouble = 0x0040;
static const KindOf KindOfString = 0x0080;
static const KindOf KindOfArray = 0x0100;
static const KindOf KindOfObject = 0x0200; // with classname
static const KindOf KindOfVariant = 0xFFFF;
/* This bit tells coerce that if the other type
is already one of the specified types, it wont
be modified.
eg $a['foo'] = <whatever>
If $a is already known to be string or array, it stays that way.
If we coerce to Sequence, however, it would become Sequence, and
hence Variant
*/
static const KindOf KindOfAuto = 0x0400;
static const KindOf KindOfInteger = (KindOf)(KindOfInt64 | KindOfInt32);
static const KindOf KindOfNumeric = (KindOf)(KindOfDouble | KindOfInteger);
static const KindOf KindOfPrimitive = (KindOf)(KindOfNumeric | KindOfString);
static const KindOf KindOfPlusOperand = (KindOf)(KindOfNumeric | KindOfArray);
static const KindOf KindOfSequence = (KindOf)(KindOfString | KindOfArray);
static const KindOf KindOfAutoSequence = (KindOf)(KindOfAuto |KindOfSequence);
static const KindOf KindOfAutoObject = (KindOf)(KindOfAuto | KindOfObject);
static const KindOf KindOfSome = (KindOf)0x7FFE;
static const KindOf KindOfAny = (KindOf)0x7FFF;
/**
* Inferred types: types that a variable or a constant is sure to be.
*/
static TypePtr Null;
static TypePtr Boolean;
static TypePtr Int32;
static TypePtr Int64;
static TypePtr Double;
static TypePtr String;
static TypePtr Array;
static TypePtr Object;
static TypePtr Variant;
static TypePtr Numeric;
static TypePtr PlusOperand;
static TypePtr Primitive;
static TypePtr Sequence;
static TypePtr AutoSequence;
static TypePtr AutoObject;
static TypePtr Any;
static TypePtr Some;