void QSEngine::registerType(QSClass *c) { QSClass *glob = env()->globalClass(); glob->addStaticVariableMember(c->identifier(), env()->typeClass()->createType(c), AttributeExecutable); }
QSObject QSObject::getQualified(const QString &name) const { QSObject obj = *this; QString s = name; // break up dotted notation ns like P1.P2.P3 while (!s.isEmpty()) { int pos = s.find('.'); if (pos < 0) pos = s.length(); // don't overwrite any existing objects, reuse them QString cname = s.left(pos); QSObject tmpobj = obj.get(cname); // Search the class hieriarchy for member if undefined if (!tmpobj.isDefined()) { QSClass *base = obj.objectType()->base(); while (base && !tmpobj.isDefined()) { tmpobj = base->get(&obj, cname); base = base->base(); } if (!tmpobj.isDefined()) return env()->createUndefined(); } obj = tmpobj; s = s.mid(pos + 1); } return obj; }
void QSParameterNode::check( QSCheckData * c ) { Q_ASSERT( c->inFunction() ); QSClass * cl = c->currentScope(); if (id == QString::fromLatin1("arguments")) { c->addError(this, QString::fromLatin1("Parameter 'arguments' is a predefined value in function '%1'. Use different parameter name.") .arg(cl->identifier())); return; } QSMember m; if( cl->member( 0, id, &m ) ) { c->addError( this, QString::fromLatin1( "Parameter '%1' already declared in function '%2'" ) .arg( id ) .arg( cl->identifier() ) ); return; } cl->addVariableMember( id, AttributeNone ); if( next ) next->check( c ); // create a member from id // add member to current scope // next.check(); }
void QSCatchNode::checkStatement( QSCheckData *c ) { checkIfGlobalAllowed( c ); QSClass *cl = c->currentScope(); index = cl->addVariableMember( ident, AttributeNone ); block->check( c ); }
QSClass *QSEnv::classByIdentifier(const QString &n) { QPtrListIterator<QSClass> it(classList); QSClass *cl; while ((cl = it()) != 0) { if (cl->identifier() == n) return cl; } return 0; }
QStringList QuickInterpreter::classes() const { QPtrList<QSClass> clsLst = env()->classes(); QStringList lst; for ( QSClass *cls = clsLst.first(); cls; cls = clsLst.next() ) { if ( cls->asClass() ) lst << cls->asClass()->identifier(); } return lst; }
void QSCheckData::registerType( QSClass *t ) { Q_ASSERT( !t->asClass() ); QSClass * scope = currentScope(); // ### Uncertain as to use identifier or name here? QSMember member; Q_ASSERT( !scope->member( 0, t->identifier(), &member ) ); scope->addStaticVariableMember( t->identifier(), env()->typeClass()->createType(t), AttributeExecutable ); }
void QSProgramNode::check( QSCheckData *c ) { if ( source ) source->check( c ); QSClass *cl = c->currentScope(); if( cl->numVariables() < c->varBlockCount() ) { cl->setNumVariables( c->varBlockCount() ); } ( (QSInstanceData*) c->env()->currentScope().shVal() )-> ensureSize( c->currentScope()->numVariables(), c->env()->createUndefined() ); }
void QSVarBindingNode::check( QSCheckData *c ) { var->check( c ); if ( assign ) assign->check( c ); if (!c->directLookupEnabled()) { c->addError( this, QString::fromLatin1( "QSA does not support declaring variables inside " "a 'with' block" )); return; } int attrs = c->lastAttributes(); QSClass * cl = c->currentScope(); QSMember m; if ( cl->member( 0, var->identifier(), &m ) ) { if( cl->asClass() ) { c->addError( this, QString::fromLatin1( "Variable '%1' has already been " "declared in class '%2'" ) .arg( var->identifier() ) .arg( cl->identifier() ) ); return; } m = QSMember( QSMember::Variable, 0, attrs ); cl->replaceMember( var->identifier(), &m ); idx = m.index(); } else { idx = cl->addVariableMember( var->identifier(), attrs ); } // store pointer to init node if this is a class member QSClassClass *clcl = cl->asClass(); if ( clcl ) { if( attrs & AttributeStatic ) clcl->addStaticInitializer( assign ); else clcl->addMemberInitializer( assign ); idx = -1; // Disable the variable binding node. } }
void QSResolveNode::check( QSCheckData *c ) { if ( !c->directLookupEnabled() ) return; QSClass * cl = c->currentScope(); QSClass *cont = cl; int uplvl = 0; int blocks = 0; QSMember member; while ( cont ) { QSMember mem; if ( cont->member( 0, ident, &mem ) ) { if ( mem.type()==QSMember::Variable && !mem.isStatic() ) { member = mem; break; } } uplvl++; cont = cont->enclosingClass(); } if( member.isDefined() ) { /* If the containing class has an undefined base, the indexes will be moved when the we call QSAbstractBaseClass::replace() and the lookup info will be crap. Therefore, we don't create it. */ QSClass *tmp = cont->base(); while (tmp) { if (tmp->name() == QString::fromLatin1("AbstractBase")) return; tmp = tmp->base(); } // Due to special handling of block scopes in the global object... if( cont==c->env()->globalClass() ) uplvl+=blocks; info = new QSLookupInfo( uplvl, member ); } }
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 ); }
void QSEnv::clear() { shutDown = TRUE; Q_ASSERT(scopeChain); // protection against consecutive calls delete scopeChain; scopeChain = 0; // lose class references thVal.invalidate(); exVal.invalidate(); retVal.invalidate(); QPtrListIterator<QSClass> it(classList); QSClass *cur; while ((cur = it())) cur->finalize(); // invalidate & delete QSShared that might still hang // around due to cyclic references QSShared *sh = sharedList; while ((sh = sh->next)) sh->invalidate(); #if QS_DEBUG_MEM == 1 // flag check for in ~QSObject() qs_finalDeletion = TRUE; #endif sh = sharedList->next; while (sh) { QSShared *next = sh->next; delete sh; sh = next; } delete sharedList; #if QS_DEBUG_MEM == 1 qs_finalDeletion = FALSE; #endif it = QPtrListIterator<QSClass>(classList); while ((cur = it())) cur->clear(); classList.clear(); objClass = 0; undefClass = 0; nilClass = 0; boolClass = 0; numClass = 0; strClass = 0; charClass = 0; typClass = 0; datClass = 0; matClass = 0; regClass = 0; arrClass = 0; errClass = 0; globClass = 0; argsClass = 0; dynClass = 0; refClass = 0; dbgClass = 0; sysClass = 0; shutDown = FALSE; }