PageRenderTime 188ms CodeModel.GetById 36ms RepoModel.GetById 1ms app.codeStats 0ms

/qsa-x11-free-1.1.5/src/engine/qsfuncref.cpp

#
C++ | 231 lines | 170 code | 27 blank | 34 comment | 35 complexity | 1bf5cc555cab58216fdc172949dd905b MD5 | raw file
Possible License(s): GPL-2.0
  1. /****************************************************************************
  2. ** $Id: qsfuncref.cpp 1.1.5 edited 2006-02-23T15:39:57$
  3. **
  4. ** Copyright (C) 2001-2006 Trolltech AS. All rights reserved.
  5. **
  6. ** This file is part of the Qt Script for Applications framework (QSA).
  7. **
  8. ** This file may be distributed and/or modified under the terms of the
  9. ** GNU General Public License version 2 as published by the Free Software
  10. ** Foundation and appearing in the file LICENSE.GPL included in the
  11. ** packaging of this file.
  12. **
  13. ** Licensees holding a valid Qt Script for Applications license may use
  14. ** this file in accordance with the Qt Script for Applications License
  15. ** Agreement provided with the Software.
  16. **
  17. ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
  18. ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  19. **
  20. ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
  21. ** information about QSA Commercial License Agreements.
  22. ** See http://www.trolltech.com/gpl/ for GPL licensing information.
  23. **
  24. ** Contact info@trolltech.com if any conditions of this licensing are
  25. ** not clear to you.
  26. **
  27. *****************************************************************************/
  28. #include "qsfuncref.h"
  29. #include "qslexer.h"
  30. #include "qsnodes.h"
  31. #include "qserror_object.h"
  32. extern int qsyyparse();
  33. /*! \reimp */
  34. QSObject QSFuncRefClass::cast( const QSList &args ) const
  35. {
  36. return construct( args );
  37. }
  38. QSObject QSFuncRefClass::construct( const QSList &args ) const
  39. {
  40. // ###
  41. QString p = QString::fromLatin1("");
  42. QString body;
  43. int argsSize = args.size();
  44. if (argsSize == 0) {
  45. body = "";
  46. } else if (argsSize == 1) {
  47. body = args[0].toString();
  48. } else {
  49. p = args[0].toString();
  50. for (int k = 1; k < argsSize - 1; k++)
  51. p += QString::fromLatin1(",") + args[k].toString();
  52. body = args[argsSize-1].toString();
  53. }
  54. QSLexer::lexer()->setCode( body, -1 );
  55. if ( qsyyparse() ) {
  56. /* TODO: free nodes */
  57. return env()->throwError( SyntaxError, QString::fromLatin1("Syntax error in function body") );
  58. }
  59. QSFunctionScopeClass *scope =
  60. new QSFunctionScopeClass( env()->objectClass() );
  61. QSFunctionBodyNode * bodyNode = QSProgramNode::last();
  62. bodyNode->setScopeDefinition( scope );
  63. scope->setFunctionBodyNode(bodyNode);
  64. QSMember mem( bodyNode );
  65. // parse parameter list. throw syntax error on illegal identifiers
  66. int len = p.length();
  67. const QChar *c = p.unicode();
  68. int i = 0, params = 0;
  69. QString param;
  70. while (i < len) {
  71. while (*c == ' ' && i < len)
  72. c++, i++;
  73. if ( QSLexer::isIdentLetter( c->unicode() ) ) { // else error
  74. param = QString(c, 1);
  75. c++, i++;
  76. while (i < len && ( QSLexer::isIdentLetter( c->unicode() ) ||
  77. QSLexer::isDecimalDigit( c->unicode() ) ) ) {
  78. param += QString(c, 1);
  79. c++, i++;
  80. }
  81. while (i < len && *c == ' ')
  82. c++, i++;
  83. if (i == len) {
  84. int index = scope->addVariableMember( param, AttributeNone );
  85. Q_ASSERT( params==index );
  86. params++;
  87. break;
  88. } else if (*c == ',') {
  89. int index = scope->addVariableMember( param, AttributeNone );
  90. Q_ASSERT( params==index );
  91. params++;
  92. c++, i++;
  93. continue;
  94. } // else error
  95. }
  96. return env()->throwError( SyntaxError, QString::fromLatin1("Syntax error in parameter list") );
  97. }
  98. scope->setNumArguments( params );
  99. return createReference( env()->currentScope(), mem );
  100. }
  101. bool QSFuncRefClass::toBoolean( const QSObject * ) const
  102. {
  103. return TRUE;
  104. }
  105. double QSFuncRefClass::toNumber( const QSObject * ) const
  106. {
  107. return NaN;
  108. }
  109. QString QSFuncRefClass::toString( const QSObject * ) const
  110. {
  111. return QString::fromLatin1("function"); // ###
  112. }
  113. class QSReferenceData : public QSShared {
  114. public:
  115. QSReferenceData( const ScopeChain &ctx, const QSObject &bs, const QSMember &mem )
  116. : context( ctx ), base( bs ), member( mem )
  117. {
  118. // printf("QSReferenceData::QSReferenceData()\n");
  119. if (member.type() == QSMember::ScriptFunction)
  120. member.scriptFunction->ref();
  121. }
  122. ~QSReferenceData()
  123. {
  124. // printf("QSReferenceData::~QSReferenceData()\n");
  125. if (member.type() == QSMember::ScriptFunction) {
  126. if (member.scriptFunction->deref())
  127. delete member.scriptFunction;
  128. }
  129. }
  130. ScopeChain context;
  131. QSObject base;
  132. QSMember member;
  133. void invalidate()
  134. {
  135. base.invalidate();
  136. ScopeChain::Iterator it = context.begin();
  137. while( it!=context.end() ) {
  138. (*it).invalidate();
  139. it++;
  140. }
  141. }
  142. };
  143. QSObject QSFuncRefClass::invoke( QSObject * objPtr,
  144. const QSMember & ) const
  145. {
  146. Q_ASSERT( objPtr->isA( this ) );
  147. QSReferenceData * data = (QSReferenceData*) objPtr->shVal();
  148. QSObject base = data->base;
  149. QSMember bmem = data->member;
  150. env()->pushScopeBlock();
  151. ScopeChain::const_iterator it = data->context.begin();
  152. while( it!=data->context.end() ) {
  153. env()->pushScope( *it );
  154. it++;
  155. }
  156. QSObject retVal = base.invoke( bmem, *(env()->arguments()) );
  157. env()->popScopeBlock();
  158. return retVal;
  159. }
  160. QSObject QSFuncRefClass::createReference( const QSObject &base,
  161. const QSMember &mem ) const
  162. {
  163. ScopeChain chain = env()->scope();
  164. // Reversed order for simplified iteration later.
  165. ScopeChain context;
  166. ScopeChain::const_iterator it = chain.begin();
  167. while( it!=chain.end() ) {
  168. context.push_front( *it );
  169. it++;
  170. }
  171. return env()->createShared( this, new QSReferenceData( context, base, mem ) );
  172. }
  173. QSMember QSFuncRefClass::refMember( const QSObject &ref )
  174. {
  175. if( ref.isFunction() ) {
  176. return ( (QSReferenceData*) ref.shVal() )->member;
  177. }
  178. qWarning( "QSFuncRefClass::refMember() - not a reference" );
  179. return QSMember();
  180. }
  181. QSObject QSFuncRefClass::refBase( const QSObject &ref )
  182. {
  183. if( ref.isFunction() ) {
  184. return ( (QSReferenceData*) ref.shVal() )->base;
  185. }
  186. qWarning( "QSFuncRefClass::refBase() - not a reference" );
  187. return ref.env()->createUndefined();
  188. }
  189. ScopeChain QSFuncRefClass::refScope( const QSObject &ref )
  190. {
  191. if( ref.isFunction() ) {
  192. return ( (QSReferenceData*) ref.shVal() )->context;
  193. }
  194. qWarning( "QSFuncRefClass::refScope() - not a reference" );
  195. return ScopeChain();
  196. }
  197. QSEqualsResult QSFuncRefClass::isEqual( const QSObject &a, const QSObject &b ) const
  198. {
  199. if( a.objectType() == b.objectType() )
  200. return ( QSEqualsResult )
  201. ( refBase( a ).equals( refBase( b ) )
  202. && refMember( a ) == refMember( b ) );
  203. return EqualsNotEqual;
  204. }