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