示例#1
0
static Array HHVM_METHOD(Closure, __debugInfo) {
  auto closure = c_Closure::fromObject(this_);

  Array ret = Array::Create();

  // Serialize 'use' parameters.
  if (auto useVars = closure->getUseVars()) {
    Array use;

    auto cls = this_->getVMClass();
    auto propsInfo = cls->declProperties();
    auto nProps = cls->numDeclProperties();
    for (size_t i = 0; i < nProps; ++i) {
      auto value = &useVars[i];
      use.setWithRef(Variant(StrNR(propsInfo[i].name)), tvAsCVarRef(value));
    }

    if (!use.empty()) {
      ret.set(s_static, use);
    }
  }

  auto const func = closure->getInvokeFunc();

  // Serialize function parameters.
  if (auto nParams = func->numParams()) {
   Array params;

   auto lNames = func->localNames();
   for (int i = 0; i < nParams; ++i) {
      auto str = String::attach(
        StringData::Make(s_varprefix.get(), lNames[i])
      );

      bool optional = func->params()[i].phpCode;
      if (auto mi = func->methInfo()) {
        optional = optional || mi->parameters[i]->valueText;
      }

      params.set(str, optional ? s_optional : s_required);
    }

    ret.set(s_parameter, params);
  }

  // Serialize 'this' object.
  if (closure->hasThis()) {
    ret.set(s_this, Object(closure->getThis()));
  }

  return ret;
}
示例#2
0
Array c_Closure::t___debuginfo() {
  Array ret = Array::Create();

  // Serialize 'use' parameters.
  if (auto propValues = propVec()) {
    Array use;

    auto propsInfo = getVMClass()->declProperties();
    for (size_t i = 0; i < getVMClass()->numDeclProperties(); ++i) {
      auto value = &propValues[i];
      use.setWithRef(Variant(StrNR(propsInfo[i].name)), tvAsCVarRef(value));
    }

    if (!use.empty()) {
      ret.set(s_static, use);
    }
  }

  auto const func = getInvokeFunc();

  // Serialize function parameters.
  if (func->numParams()) {
   Array params;

   for (int i = 0; i < func->numParams(); ++i) {
      auto str = String::attach(
        StringData::Make(s_varprefix.get(), func->localNames()[i])
      );

      bool optional = func->params()[i].phpCode;
      if (auto mi = func->methInfo()) {
        optional = optional || mi->parameters[i]->valueText;
      }

      params.set(str, optional ? s_optional : s_required);
    }

    ret.set(s_parameter, params);
  }

  // Serialize 'this' object.
  if (hasThis()) {
    ret.set(s_this, Object(getThis()));
  }

  return ret;
}
示例#3
0
//------------------------------------------------------------------------------
/*virtual*/ bool FunctionForEach::ParseFunction(
                    NodeGraph & nodeGraph,
                    const BFFIterator & functionNameStart,
                    const BFFIterator * functionBodyStartToken,
                    const BFFIterator * functionBodyStopToken,
                    const BFFIterator * functionHeaderStartToken,
                    const BFFIterator * functionHeaderStopToken ) const
{
    // build array for each pair to loop through
    Array< AString >                localNames( 4, true );
    Array< const BFFVariable * >    arrayVars( 4, true );

    int loopLen = -1;

    // parse it all out
    BFFIterator pos( *functionHeaderStartToken );
    pos++; // skip opening token
    while ( pos < *functionHeaderStopToken )
    {
        pos.SkipWhiteSpace();
        if ( *pos != BFFParser::BFF_DECLARE_VAR_INTERNAL )
        {
            Error::Error_1200_ExpectedVar( pos, this );
            return false;
        }

        const BFFIterator arrayVarNameBegin = pos;
        AStackString< BFFParser::MAX_VARIABLE_NAME_LENGTH > localName;
        bool localParentScope = false; // always false thanks to the previous test
        if ( BFFParser::ParseVariableName( pos, localName, localParentScope ) == false )
        {
            return false;
        }
        ASSERT( false == localParentScope );

        localNames.Append( localName );

        pos.SkipWhiteSpace();

        // check for "in" token
        bool foundIn = false;
        if ( *pos == 'i' )
        {
            pos++;
            if ( *pos == 'n' )
            {
                foundIn = true;
            }
        }
        if ( foundIn == false )
        {
            Error::Error_1201_MissingIn( pos, this );
            return false;
        }
        pos++;
        pos.SkipWhiteSpace();

        if ( *pos != BFFParser::BFF_DECLARE_VAR_INTERNAL &&
             *pos != BFFParser::BFF_DECLARE_VAR_PARENT /* tolerant with parent vars */ )
        {
            Error::Error_1202_ExpectedVarFollowingIn( pos, this );
            return false;
        }

        const BFFIterator arrayNameStart( pos );
        AStackString< BFFParser::MAX_VARIABLE_NAME_LENGTH > arrayVarName;
        bool arrayParentScope = false;
        if ( BFFParser::ParseVariableName( pos, arrayVarName, arrayParentScope ) == false )
        {
            return false;
        }

        const BFFVariable * var = nullptr;
        BFFStackFrame * const arrayFrame = ( arrayParentScope )
            ? BFFStackFrame::GetParentDeclaration( arrayVarName, BFFStackFrame::GetCurrent()->GetParent(), var )
            : nullptr;

        if ( false == arrayParentScope )
        {
            var = BFFStackFrame::GetVar( arrayVarName, nullptr );
        }

        if ( ( arrayParentScope && ( nullptr == arrayFrame ) ) || ( var == nullptr ) )
        {
            Error::Error_1009_UnknownVariable( arrayNameStart, this, arrayVarName );
            return false;
        }

        // it can be of any supported type
        if ( ( var->IsArrayOfStrings() == false ) && ( var->IsArrayOfStructs() == false ) )
        {
            Error::Error_1050_PropertyMustBeOfType( arrayVarNameBegin, this, arrayVarName.Get(), var->GetType(), BFFVariable::VAR_ARRAY_OF_STRINGS, BFFVariable::VAR_ARRAY_OF_STRUCTS );
            return false;
        }

        // is this the first variable?
        int thisArrayLen( -1 );
        if ( var->GetType() == BFFVariable::VAR_ARRAY_OF_STRINGS )
        {
            thisArrayLen = (int)var->GetArrayOfStrings().GetSize();
        }
        else if ( var->GetType() == BFFVariable::VAR_ARRAY_OF_STRUCTS )
        {
            thisArrayLen = (int)var->GetArrayOfStructs().GetSize();
        }
        else
        {
            ASSERT( false );
        }

        if ( loopLen == -1 )
        {
            // it will set the length of looping
            loopLen = thisArrayLen;
        }
        else
        {
            // variables after the first must match length of the first
            if ( loopLen != thisArrayLen )
            {
                Error::Error_1204_LoopVariableLengthsDiffer( arrayVarNameBegin, this, arrayVarName.Get(), (uint32_t)thisArrayLen, (uint32_t)loopLen );
                return false;
            }
        }
        arrayVars.Append( var );

        // skip optional separator
        pos.SkipWhiteSpace();
        if ( *pos == ',' )
        {
            pos++;
        }
    }

    ASSERT( localNames.GetSize() == arrayVars.GetSize() );

    // gracefully allow empty loops
    if ( loopLen < 1 )
    {
        return true;
    }

    // freeze the variable to avoid modifications while looping
    for ( uint32_t j=0; j<arrayVars.GetSize(); ++j )
    {
        arrayVars[ j ]->Freeze();
        FLOG_INFO( "Freezing loop array '%s' of type <%s>",
                   arrayVars[j]->GetName().Get(), BFFVariable::GetTypeName( arrayVars[j]->GetType() ) );
    }

    bool succeed = true;

    for ( uint32_t i=0; i<(uint32_t)loopLen; ++i )
    {
        // create local loop variables
        BFFStackFrame loopStackFrame;
        for ( uint32_t j=0; j<localNames.GetSize(); ++j )
        {
            if ( arrayVars[ j ]->GetType() == BFFVariable::VAR_ARRAY_OF_STRINGS )
            {
                BFFStackFrame::SetVarString( localNames[ j ], arrayVars[ j ]->GetArrayOfStrings()[ i ], &loopStackFrame );
            }
            else if ( arrayVars[ j ]->GetType() == BFFVariable::VAR_ARRAY_OF_STRUCTS )
            {
                BFFStackFrame::SetVarStruct( localNames[ j ], arrayVars[ j ]->GetArrayOfStructs()[ i ]->GetStructMembers(), &loopStackFrame );
            }
            else
            {
                ASSERT( false );
            }
        }

        // parse the function body
        BFFParser subParser( nodeGraph );
        BFFIterator subIter( *functionBodyStartToken );
        subIter++; // skip opening token
        subIter.SetMax( functionBodyStopToken->GetCurrent() ); // limit to closing token
        if ( subParser.Parse( subIter ) == false )
        {
            succeed = false;
            break;
        }

        // complete the function
        if ( Commit( nodeGraph, functionNameStart ) == false )
        {
            succeed = false;
            break;
        }
    }

    // unfreeze all array variables
    for ( uint32_t j=0; j<arrayVars.GetSize(); ++j )
    {
        arrayVars[ j ]->Unfreeze();
        FLOG_INFO( "Unfreezing loop array '%s' of type <%s>",
                   arrayVars[j]->GetName().Get(), BFFVariable::GetTypeName( arrayVars[j]->GetType() ) );
    }

    return succeed;
}