xref: /trunk/main/basic/source/comp/exprgen.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_basic.hxx"
30 
31 #include "sbcomp.hxx"
32 #include "expr.hxx"
33 
34 // Umsetztabelle fuer Token-Operatoren und Opcodes
35 
36 typedef struct {
37         SbiToken  eTok;                 // Token
38         SbiOpcode eOp;                  // Opcode
39 } OpTable;
40 
41 static OpTable aOpTable [] = {
42     { EXPON,_EXP },
43     { MUL,  _MUL },
44     { DIV,  _DIV },
45     { IDIV, _IDIV },
46     { MOD,  _MOD },
47     { PLUS, _PLUS },
48     { MINUS,_MINUS },
49     { EQ,   _EQ },
50     { NE,   _NE },
51     { LE,   _LE },
52     { GE,   _GE },
53     { LT,   _LT },
54     { GT,   _GT },
55     { AND,  _AND },
56     { OR,   _OR },
57     { XOR,  _XOR },
58     { EQV,  _EQV },
59     { IMP,  _IMP },
60     { NOT,  _NOT },
61     { NEG,  _NEG },
62     { CAT,  _CAT },
63     { LIKE, _LIKE },
64     { IS,   _IS },
65     { NIL,  _NOP }};
66 
67 // Ausgabe eines Elements
68 void SbiExprNode::Gen( RecursiveMode eRecMode )
69 {
70     if( IsConstant() )
71     {
72         switch( GetType() )
73         {
74             case SbxEMPTY:   pGen->Gen( _EMPTY ); break;
75             case SbxINTEGER: pGen->Gen( _CONST,  (short) nVal ); break;
76             case SbxSTRING:
77             {
78                 sal_uInt16 nStringId = pGen->GetParser()->aGblStrings.Add( aStrVal, sal_True );
79                 pGen->Gen( _SCONST, nStringId ); break;
80             }
81             default:
82             {
83                 sal_uInt16 nStringId = pGen->GetParser()->aGblStrings.Add( nVal, eType );
84                 pGen->Gen( _NUMBER, nStringId );
85             }
86         }
87     }
88     else if( IsOperand() )
89     {
90         SbiExprNode* pWithParent_ = NULL;
91         SbiOpcode eOp;
92         if( aVar.pDef->GetScope() == SbPARAM )
93         {
94             eOp = _PARAM;
95             if( 0 == aVar.pDef->GetPos() )
96             {
97                 bool bTreatFunctionAsParam = true;
98                 if( eRecMode == FORCE_CALL )
99                 {
100                     bTreatFunctionAsParam = false;
101                 }
102                 else if( eRecMode == UNDEFINED )
103                 {
104                     if( aVar.pPar && aVar.pPar->IsBracket() )
105                         bTreatFunctionAsParam = false;
106                 }
107                 if( !bTreatFunctionAsParam )
108                     eOp = aVar.pDef->IsGlobal() ? _FIND_G : _FIND;
109             }
110         }
111         // AB: 17.12.1995, Spezialbehandlung fuer WITH
112         else if( (pWithParent_ = GetWithParent()) != NULL )
113         {
114             eOp = _ELEM;            // .-Ausdruck in WITH
115         }
116         else
117         {
118             eOp = ( aVar.pDef->GetScope() == SbRTL ) ? _RTL :
119                 (aVar.pDef->IsGlobal() ? _FIND_G : _FIND);
120         }
121 
122         if( eOp == _FIND )
123         {
124 
125             SbiProcDef* pProc = aVar.pDef->GetProcDef();
126             if ( pGen->GetParser()->bClassModule )
127                 eOp = _FIND_CM;
128             else if ( aVar.pDef->IsStatic() || (pProc && pProc->IsStatic()) )
129             {
130                 eOp = _FIND_STATIC;
131             }
132         }
133         for( SbiExprNode* p = this; p; p = p->aVar.pNext )
134         {
135             if( p == this && pWithParent_ != NULL )
136                 pWithParent_->Gen();
137             p->GenElement( eOp );
138             eOp = _ELEM;
139         }
140     }
141     else if( IsTypeOf() )
142     {
143         pLeft->Gen();
144         pGen->Gen( _TESTCLASS, nTypeStrId );
145     }
146     else if( IsNew() )
147     {
148         pGen->Gen( _CREATE, 0, nTypeStrId );
149     }
150     else
151     {
152         pLeft->Gen();
153         if( pRight )
154             pRight->Gen();
155         for( OpTable* p = aOpTable; p->eTok != NIL; p++ )
156         {
157             if( p->eTok == eTok )
158             {
159                 pGen->Gen( p->eOp ); break;
160             }
161         }
162     }
163 }
164 
165 // Ausgabe eines Operanden-Elements
166 
167 void SbiExprNode::GenElement( SbiOpcode eOp )
168 {
169 #ifdef DBG_UTIL
170     if( (eOp < _RTL || eOp > _CALLC) && eOp != _FIND_G && eOp != _FIND_CM )
171         pGen->GetParser()->Error( SbERR_INTERNAL_ERROR, "Opcode" );
172 #endif
173     SbiSymDef* pDef = aVar.pDef;
174     // Das ID ist entweder die Position oder das String-ID
175     // Falls das Bit 0x8000 gesetzt ist, hat die Variable
176     // eine Parameterliste.
177     sal_uInt16 nId = ( eOp == _PARAM ) ? pDef->GetPos() : pDef->GetId();
178     // Parameterliste aufbauen
179     if( aVar.pPar && aVar.pPar->GetSize() )
180     {
181         nId |= 0x8000;
182         aVar.pPar->Gen();
183     }
184 
185     pGen->Gen( eOp, nId, sal::static_int_cast< sal_uInt16 >( GetType() ) );
186 
187     if( aVar.pvMorePar )
188     {
189         SbiExprListVector* pvMorePar = aVar.pvMorePar;
190         SbiExprListVector::iterator it;
191         for( it = pvMorePar->begin() ; it != pvMorePar->end() ; ++it )
192         {
193             SbiExprList* pExprList = *it;
194             pExprList->Gen();
195             pGen->Gen( _ARRAYACCESS );
196         }
197     }
198 }
199 
200 // Erzeugen einer Argv-Tabelle
201 // Das erste Element bleibt immer frei fuer Returnwerte etc.
202 // Siehe auch SbiProcDef::SbiProcDef() in symtbl.cxx
203 
204 void SbiExprList::Gen()
205 {
206     if( pFirst )
207     {
208         pParser->aGen.Gen( _ARGC );
209         // AB 10.1.96: Typ-Anpassung bei DECLARE
210         sal_uInt16 nCount = 1 /*, nParAnz = 0*/;
211 //      SbiSymPool* pPool = NULL;
212         for( SbiExpression* pExpr = pFirst; pExpr; pExpr = pExpr->pNext,nCount++ )
213         {
214             pExpr->Gen();
215             if( pExpr->GetName().Len() )
216             {
217                 // named arg
218                 sal_uInt16 nSid = pParser->aGblStrings.Add( pExpr->GetName() );
219                 pParser->aGen.Gen( _ARGN, nSid );
220 
221                 /* TODO: Check after Declare concept change
222                 // AB 10.1.96: Typanpassung bei named -> passenden Parameter suchen
223                 if( pProc )
224                 {
225                     // Vorerst: Error ausloesen
226                     pParser->Error( SbERR_NO_NAMED_ARGS );
227 
228                     // Spaeter, wenn Named Args bei DECLARE moeglich
229                     //for( sal_uInt16 i = 1 ; i < nParAnz ; i++ )
230                     //{
231                     //  SbiSymDef* pDef = pPool->Get( i );
232                     //  const String& rName = pDef->GetName();
233                     //  if( rName.Len() )
234                     //  {
235                     //      if( pExpr->GetName().ICompare( rName )
236                     //          == COMPARE_EQUAL )
237                     //      {
238                     //          pParser->aGen.Gen( _ARGTYP, pDef->GetType() );
239                     //          break;
240                     //      }
241                     //  }
242                     //}
243                 }
244                 */
245             }
246             else
247             {
248                 pParser->aGen.Gen( _ARGV );
249             }
250         }
251     }
252 }
253 
254 void SbiExpression::Gen( RecursiveMode eRecMode )
255 {
256     // AB: 17.12.1995, Spezialbehandlung fuer WITH
257     // Wenn pExpr == .-Ausdruck in With, zunaechst Gen fuer Basis-Objekt
258     pExpr->Gen( eRecMode );
259     if( bByVal )
260         pParser->aGen.Gen( _BYVAL );
261     if( bBased )
262     {
263         sal_uInt16 uBase = pParser->nBase;
264         if( pParser->IsCompatible() )
265             uBase |= 0x8000;        // #109275 Flag compatiblity
266         pParser->aGen.Gen( _BASED, uBase );
267         pParser->aGen.Gen( _ARGV );
268     }
269 }
270 
271