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; }
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 ); }
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 ); }
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); } }
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 ); }