`
saiyaren
  • 浏览: 228194 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

hiphop 原理分析4 原创--胡志广

阅读更多

下面主要分析的是优化阶段和推导阶段的分析,前优化和后优化类似,所以就不具体再分析后优化;

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;

 

  • 大小: 40 KB
  • 大小: 39.5 KB
  • 大小: 31.2 KB
  • 大小: 23 KB
  • 大小: 13.8 KB
1
2
分享到:
评论

相关推荐

    hiphop无穷动

    hiphop无穷动

    Hiphop-Step历史及名称由来.doc

    【HipHop-Step的历史与名称由来】 HipHop-Step,作为街舞文化的重要组成部分,起源于20世纪70年代末至80年代初的纽约。它的诞生源自多种舞蹈形式的融合,其中包括非洲舞蹈、Capoeira、B-Boy舞蹈、Jazz舞以及Tap舞...

    Hip Hop Wallpapers New Tab Theme-crx插件

    此扩展程序在每个新选项卡中都包括最佳嘻哈音乐人的高清图像! 说唱歌手包括Eminem Lil Wayne Drake等! 此扩展程序在每个新选项卡中都包括最佳嘻哈音乐人的高清图像! 非常适合音乐迷! 说唱歌手包括Fetty Wap,...

    NF HD Wallpapers Hip Hop Music New Tab Theme-crx插件

    获取NF的高清图像,NF是当今最好的说唱歌手之一 可以立即访问他的官方社交网站。 您好,NF的粉丝们! 每次打开新选项卡时,获取喜欢的说唱歌手的高清壁纸。 我们授予了访问他的官方Twitter帐户的权限。...

    YG HD Wallpapers Hip Hop Music New Tab Theme-crx插件

    查找流行的说唱歌手YG的高清背景 可以立即访问他的官方社交网站。 爱嘻哈吗? 喜欢YG和他的音乐吗? 如果您这样做,那么此扩展程序就是适合您的扩展程序。 每次打开新标签页,您都会获得不同的YG高清壁纸。...

    Hiphop-API:用于实时应用程序的 Hiphop API

    通过下载并分析Hiphop-API-master这个压缩包,我们可以深入研究其内部结构,包括源代码文件、文档、示例和测试等,以全面了解Hiphop API的功能和用法。此外,社区的支持和讨论也是学习和解决问题的重要资源,可以...

    Cardi B高清壁纸嘻哈新标签主题「Cardi B HD Wallpapers Hip Hop New Tab Theme」-crx插件

    Cardi B和嘻哈音乐的每个宣誓粉丝都必须拥有此扩展名。 如果您喜欢Cardi B和她的音乐,则绝对应该拥有此扩展名。 它包括流行的嘻哈艺术家的高清照片。 此外,我们添加了她的官方Twitter帐户。 因此,您将是第一个...

    Raslani Hip Hop

    "Raslani Hip Hop"可能是指一种特定的字体风格,它结合了Hip Hop文化的元素,旨在为文本内容增添独特的个性和动态感。这种字体可能广泛应用于音乐制作、广告设计、游戏界面、社交媒体帖子以及各种创意项目中,以吸引...

    Sa-HipHop App-crx插件

    Sa-HipHop,最新的南非音乐Mp3下载还包括SA Hip Hop,非洲之家,深层之屋,Gqom,科威特,部落,Masandi和Ampiano。 Sa-HipHop:南非的灵魂音乐在Sa-HipHop的此处下载,我们随时为您提供最好,最精彩的Sa Hip Hop和...

    HIP与NOW缺陷的解析 -- 适普(中国)-HIP与NOW缺陷的解析.rar

    "HIP与NOW缺陷"是两个常见的问题,尤其是在半导体制造和集成电路(IC)设计中。本文将深入探讨这两个缺陷的本质、成因以及如何进行预防和解决。 首先,HIP,全称为Heat Induced Pinholing,翻译为热诱导针孔缺陷。...

    Hip Hop Beats and Instrumentals Online-crx插件

    每个人都喜欢Hip Hop音乐和Hip Hop Beats,现在Trap成为都市音乐界的一种趋势。 这就是为什么如果您是一名艺术家,则必须获得最好的嘻哈节拍和器乐。 不管他们是R&B,Smooth,Trap还是New School ...他们都必须听...

    简单hiphop街舞教学视频.doc

    简单hiphop街舞教学视频.doc

    West Coast Hip Hop Beats and Instrumentals-crx插件

    您是否在为下一个项目寻找West Coast,Gangsta,G-Funk或Hip Hop Beats和Instrumental? 这是你的地方! 许多人在节拍和器乐中寻找那种高品质的声音,这些声音使人想起了旧学校和西海岸的嘻哈音乐的开端,但是却没有...

    billboard-hiphop-chart-api

    其中,广告牌(Billboard)的嘻哈图表(Hip-Hop Chart)更是备受关注,它反映了当下最热门的嘻哈音乐趋势。本篇文章将围绕“广告牌嘻哈图表API”展开,探讨如何利用Python语言与其进行交互,获取并分析实时的嘻哈...

    Lil Pump高清壁纸嘻哈音乐主题「Lil Pump HD Wallpapers Hip Hop Music Theme」-crx插件

    享受您最喜爱的Hip Hop艺术家的高清图像 - Lil Pump。每个新标签都会获得不同的壁纸。 如果您喜欢嘻哈音乐,那么您肯定对Lil Pump有所了解。 我们添加了您最喜欢的艺术家的高清背景。 此外,借助我们的Twitter小部件...

    Weeknd高清壁纸嘻哈RnB主题「The Weeknd HD Wallpapers Hip Hop RnB Theme」-crx插件

    安装此扩展程序并享受您最喜爱的RnB和Hip Hop艺术家的高清背景 - The Weeknd。 您喜欢RnB和嘻哈音乐吗? 您喜欢The Weeknd吗? 如果您这样做,那么此扩展名仅适合您。 每个新标签页都会为您显示不同的高清背景或The ...

Global site tag (gtag.js) - Google Analytics