Ejemplo n.º 1
0
QStringList QuickInterpreter::functionsOf(QSObject &obj, bool includeSignature, bool includeNative, bool includeMemberFunctions) const
{
    const QSClass *objType = obj.objectType();
    QSMemberMap mmap = objType == env()->typeClass() && includeMemberFunctions
		       ? ((QSTypeClass*) objType)->allMembers(&obj)
		       : objType->members(&obj);

    QMap<int, QString> functions;
    for (QSMemberMap::Iterator it = mmap.begin(); it != mmap.end(); ++it) {
	if (((*it).type() == QSMember::ScriptFunction ||
	       includeNative && ((*it).type() == QSMember::NativeFunction ||
				  (*it).type() == QSMember::NativeMemberFunction))
	     && !(*it).isPrivate()) {
	    QString func = (*it).name();
	    // ### will break with mix of script and C++ functions
	    int idx = (*it).type() == QSMember::ScriptFunction ?
		      (*it).scriptFunction->index() : functions.size();
	    if (includeSignature) {
		if ((*it).type() == QSMember::NativeFunction ||
		     (*it).type() == QSMember::NativeMemberFunction) {
		    func += QString::fromLatin1("()");
		} else {
		    QSFunctionScopeClass *fsc = (*it).scriptFunction->scopeDefinition();
		    int args = fsc->numArguments();
		    func += QString::fromLatin1("(");
		    if (args > 0) {
			func += QString::fromLatin1(" ");
			QSMemberMap *members = fsc->definedMembers();
			QVector<QString> vec(args);
			for (QSMemberMap::ConstIterator ait = members->begin();
			      ait != members->end(); ++ait) {
			    if ((*ait).index() < args)
				vec[ (*ait).index() ] = (*ait).name();
			}
			for (int i = 0; i < args; ++i) {
			    if (i > 0)
				func += QString::fromLatin1(", ");
			    func += vec[i];
			}
			func += QString::fromLatin1(" ");
		    }
		    func += QString::fromLatin1(")");
		}
	    }
	    functions[idx] = func;
	}
    }

    // assemble to list sorted by original index
    QStringList lst;
    QMap<int, QString>::const_iterator cit = functions.begin();
    for (; cit != functions.end(); ++cit)
	    lst << *cit;

    return lst;
}
Ejemplo n.º 2
0
void QSFuncExprNode::check( QSCheckData *c )
{
    // ### Check attributes and refactor code with QSFuncDeclNode
    QSClass * cl = c->currentScope();
    QSFunctionScopeClass * fscope = new QSFunctionScopeClass( c->env()->objectClass()  );
    fscope->setEnclosingClass( cl );
    body->setScopeDefinition( fscope );
    fscope->setFunctionBodyNode(body);
    c->enterFunction( fscope );
    if( param )
	param->check( c );
    body->check( c );
    c->leaveFunction();

    // Calculate the number of arguments
    int count = 0;
    QSParameterNode * node = param;
    while( node ) {
	count++;
	node = node->nextParam();
    }
    fscope->setNumArguments( count );
}
Ejemplo n.º 3
0
QSObject QSFuncRefClass::construct( const QSList &args ) const
{
    // ###
  QString p = QString::fromLatin1("");
  QString body;
  int argsSize = args.size();
  if (argsSize == 0) {
    body = "";
  } else if (argsSize == 1) {
    body = args[0].toString();
  } else {
    p = args[0].toString();
    for (int k = 1; k < argsSize - 1; k++)
      p += QString::fromLatin1(",") + args[k].toString();
    body = args[argsSize-1].toString();
  }

  QSLexer::lexer()->setCode( body, -1 );
  if ( qsyyparse() ) {
    /* TODO: free nodes */
    return env()->throwError( SyntaxError, QString::fromLatin1("Syntax error in function body") );
  }

  QSFunctionScopeClass *scope =
      new QSFunctionScopeClass( env()->objectClass() );
  QSFunctionBodyNode * bodyNode = QSProgramNode::last();
  bodyNode->setScopeDefinition( scope );
  scope->setFunctionBodyNode(bodyNode);
  QSMember mem( bodyNode );

  // parse parameter list. throw syntax error on illegal identifiers
  int len = p.length();
  const QChar *c = p.unicode();
  int i = 0, params = 0;
  QString param;
  while (i < len) {
      while (*c == ' ' && i < len)
	  c++, i++;
      if ( QSLexer::isIdentLetter( c->unicode() ) ) {  // else error
	  param = QString(c, 1);
	  c++, i++;
	  while (i < len && ( QSLexer::isIdentLetter( c->unicode() ) ||
			      QSLexer::isDecimalDigit( c->unicode() ) ) ) {
	      param += QString(c, 1);
	      c++, i++;
	  }
	  while (i < len && *c == ' ')
	      c++, i++;
	  if (i == len) {
	      int index = scope->addVariableMember( param, AttributeNone );
	      Q_ASSERT( params==index );
	      params++;
	      break;
	  } else if (*c == ',') {
	      int index = scope->addVariableMember( param, AttributeNone );
	      Q_ASSERT( params==index );
	      params++;
	      c++, i++;
	      continue;
	  } // else error
      }
      return env()->throwError( SyntaxError, QString::fromLatin1("Syntax error in parameter list") );
  }

  scope->setNumArguments( params );
  return createReference( env()->currentScope(), mem );

}
Ejemplo n.º 4
0
void QSClassDefNode::check( QSCheckData *c )
{
//     qDebug( "Class noticed: " + c->globalName( ident ) );

    // forward declaration ?
    if ( !body ) {
	c->addWarning( this, QString::fromLatin1("Forward declarations not supported, yet") );
	return;
    }

    if ( attrs )
	attrs->check( c );
    else
	c->setLastAttributes( AttributeNone );
    int as = c->lastAttributes();

    // base class
    QSClass *b = c->env()->objectClass();
    if ( type ) {
	type->check( c );
	if ( c->hasError() )
	    return;
	Q_ASSERT( c->lastType() );
	b = c->lastType();
	// try to cast
	if ( b->isFinal() ) {
	    c->addError( this, QSErrClassBaseFinal,
			 QString::fromLatin1("Base class has been declared final") );
	    return;
	}
    }

    // create new class description
    QSClass *scope = c->currentScope();
    if ( scope->name()==QString::fromLatin1("Class") ) {
	if ( !(as&AttributeStatic) ) {
	    c->addError( this, QSErrNestedClass,
			 QString::fromLatin1( "Nested class '%1' in class '%2' must be "
				  "declared static" )
			 .arg( ident ).arg( scope->identifier() ) );
	    return;
	}
    } else if ( as&AttributeStatic ) {
        c->addError( this, QSErrAttributeConflict,
		     QString::fromLatin1( "Static class '%1' cannot be declared outside "
			      "a class" ).arg( ident ) );
	return;
    } else if ( scope->name()==QString::fromLatin1("FunctionScope") ) {
	c->addError( this, QSErrNestedClass,
		     QString::fromLatin1( "Class '%1' cannot be declared inside function '%2'" )
		     .arg( ident ).arg( scope->identifier() ) );
	return;
    }

    QSClass *absBase = c->env()->classByIdentifier(ident);
    bool usesAbstractBase = absBase && absBase->name() == QString::fromLatin1("AbstractBase");

    QSClassClass *cl = new QSClassClass( b, as, ident );
    ref(); // Compensate for setClassDefNode below. Dereffed in QSClassClass destructor.
    cl->setClassDefNode( this );
    cl->setEnclosingClass( scope );

    QSMember member;
    QSObject tobj = c->env()->typeClass()->createType(cl);
    if( scope->member( 0, cl->identifier(), &member ) ) {
	scope->replaceMember( cl->identifier(), &member, tobj );
    } else {
	scope->addStaticVariableMember( cl->identifier(), tobj,
					AttributeExecutable );
    }

    c->enterClass( cl );
    body->check( c );
    c->leaveClass();

    // if there is a function with the same name it becomes the constructor
    QSMember ctor;
    if ( cl->member( 0, ident, &ctor ) ) {
	if ( ctor.isExecutable() ) {
	    cl->setHasDefaultConstructor( true );
	} else {
	    qWarning( "Constructor is no function" ); // pedantic
	}
    }

    cl->setClassBodyNode( body );
    QSFunctionScopeClass *fs = new QSFunctionScopeClass( c->env()->objectClass() );
    fs->setEnclosingClass( cl );
    body->setScopeDefinition( fs );
    fs->setFunctionBodyNode(body);

    // will be used in execute()
    this->cldef = cl;

    // If the classname exists in env and is a previously undefined type, we have to
    // replace it with this one.
    if (usesAbstractBase) {
	((QSAbstractBaseClass*)absBase)->replace(cl);
    }

}
Ejemplo n.º 5
0
void QSFuncDeclNode::check( QSCheckData *c )
{
//     qDebug( "Function noticed: " + c->globalName(ident) );
    if ( attrs )
	attrs->check( c );
    else
	c->setLastAttributes( AttributeNone );
    int as = c->lastAttributes();
    QSClass * cl = c->currentScope();
    Q_ASSERT( cl );

    if ( (as&AttributeStatic) && cl->name() != QString::fromLatin1("Class") ) {
	c->addError( this, QSErrAttrStaticContext,
		     QString::fromLatin1( "Function '%1' cannot be declared static "
			      "outside a class" ).arg( ident ) );
	return;
    }

    // A bit of magic fail early when trying to overwrite a context.
    if (c->inGlobal()) {
        QSObject object = c->env()->globalObject().get(ident);
        if (object.isValid()) {
            if (object.objectType()->name() == QString::fromLatin1("QObject")) {
                c->addError(this, QString("Cannot declare function '%1', already a global object "
                                          "present with same name").arg(ident));
                return;
            }
        }
    }

    QSMember m;
    m.setPrivate( as&AttributePrivate );

    if ( cl->member( 0, ident, &m ) ) {
        QSMember mem( body, as );
        cl->replaceMember( ident, &mem );
    } else {
	cl->addFunctionMember( ident, body, as );
    }

    int tmpVarBlockCount = c->varBlockCount();
    c->setVarBlockCount( 0 );
    QSFunctionScopeClass * fscope = new QSFunctionScopeClass( c->env()->objectClass(), this );
    fscope->setEnclosingClass( cl );
    body->setScopeDefinition( fscope );
    fscope->setFunctionBodyNode(body);
    c->enterFunction( fscope );
    if( param )
	param->check( c );
    body->check( c );
    c->leaveFunction();

    if( c->varBlockCount()>fscope->numVariables() )
	fscope->setNumVariables( c->varBlockCount() );
    c->setVarBlockCount( tmpVarBlockCount );

    // Calculate the number of arguments
    int count = 0;
    QSParameterNode * node = param;
    while( node ) {
	count++;
	node = node->nextParam();
    }
    fscope->setNumArguments( count );

    // unset attributes
    c->setLastAttributes( AttributeNone );
}