LibreOffice Module basic (master) 1
exprgen.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include <basic/sberrors.hxx>
21
22#include <codegen.hxx>
23#include <expr.hxx>
24#include <parser.hxx>
25
26// Transform table for token operators and opcodes
27
28namespace {
29
30struct OpTable {
31 SbiToken eTok; // Token
32 SbiOpcode eOp; // Opcode
33};
34
35}
36
37const OpTable aOpTable [] = {
45 { EQ, SbiOpcode::EQ_ },
46 { NE, SbiOpcode::NE_ },
47 { LE, SbiOpcode::LE_ },
48 { GE, SbiOpcode::GE_ },
49 { LT, SbiOpcode::LT_ },
50 { GT, SbiOpcode::GT_ },
52 { OR, SbiOpcode::OR_ },
60 { IS, SbiOpcode::IS_ },
61 { NIL, SbiOpcode::NOP_ }};
62
63// Output of an element
65{
66 sal_uInt16 nStringId;
67
68 if( IsConstant() )
69 {
70 switch( GetType() )
71 {
72 case SbxEMPTY:
73 rGen.Gen( SbiOpcode::EMPTY_ );
74 break;
75 case SbxSTRING:
76 nStringId = rGen.GetParser()->aGblStrings.Add( aStrVal );
77 rGen.Gen( SbiOpcode::SCONST_, nStringId );
78 break;
79 default:
80 // tdf#131296 - generate SbiOpcode::NUMBER_ instead of SbiOpcode::CONST_
81 // for SbxINTEGER and SbxLONG including their numeric value and its data type,
82 // which will be restored in SbiRuntime::StepLOADNC.
83 nStringId = rGen.GetParser()->aGblStrings.Add( nVal, eType );
84 rGen.Gen( SbiOpcode::NUMBER_, nStringId );
85 break;
86 }
87 }
88 else if( IsOperand() )
89 {
90 SbiExprNode* pWithParent_ = nullptr;
91 SbiOpcode eOp;
92 if( aVar.pDef->GetScope() == SbPARAM )
93 {
95 if( aVar.pDef->GetPos() == 0 )
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 {
106 bTreatFunctionAsParam = false;
107 }
108 }
109 if( !bTreatFunctionAsParam )
110 {
112 }
113 }
114 }
115 // special treatment for WITH
116 else if( (pWithParent_ = pWithParent) != nullptr )
117 {
118 eOp = SbiOpcode::ELEM_; // .-Term in WITH
119 }
120 else
121 {
122 eOp = ( aVar.pDef->GetScope() == SbRTL ) ? SbiOpcode::RTL_ :
124 }
125
126 if( eOp == SbiOpcode::FIND_ )
127 {
128
129 SbiProcDef* pProc = aVar.pDef->GetProcDef();
130 if ( rGen.GetParser()->bClassModule )
131 {
133 }
134 else if ( aVar.pDef->IsStatic() || (pProc && pProc->IsStatic()) )
135 {
137 }
138 }
139 for( SbiExprNode* p = this; p; p = p->aVar.pNext )
140 {
141 if( p == this && pWithParent_ != nullptr )
142 {
143 pWithParent_->Gen(rGen);
144 }
145 p->GenElement( rGen, eOp );
146 eOp = SbiOpcode::ELEM_;
147 }
148 }
149 else if( eNodeType == SbxTYPEOF )
150 {
151 pLeft->Gen(rGen);
153 }
154 else if( eNodeType == SbxNEW )
155 {
157 }
158 else
159 {
160 pLeft->Gen(rGen);
161 if( pRight )
162 {
163 pRight->Gen(rGen);
164 }
165 for( const OpTable* p = aOpTable; p->eTok != NIL; p++ )
166 {
167 if( p->eTok == eTok )
168 {
169 rGen.Gen( p->eOp ); break;
170 }
171 }
172 }
173}
174
175// Output of an operand element
176
178{
179#ifdef DBG_UTIL
180 if ((eOp < SbiOpcode::RTL_ || eOp > SbiOpcode::CALLC_) && eOp != SbiOpcode::FIND_G_ && eOp != SbiOpcode::FIND_CM_ && eOp != SbiOpcode::FIND_STATIC_)
181 rGen.GetParser()->Error( ERRCODE_BASIC_INTERNAL_ERROR, "Opcode" );
182#endif
183 SbiSymDef* pDef = aVar.pDef;
184 // The ID is either the position or the String-ID
185 // If the bit Bit 0x8000 is set, the variable have
186 // a parameter list.
187 sal_uInt16 nId = ( eOp == SbiOpcode::PARAM_ ) ? pDef->GetPos() : pDef->GetId();
188 // Build a parameter list
189 if( aVar.pPar && aVar.pPar->GetSize() )
190 {
191 nId |= 0x8000;
192 aVar.pPar->Gen(rGen);
193 }
194
195 rGen.Gen( eOp, nId, sal::static_int_cast< sal_uInt16 >( GetType() ) );
196
197 if( aVar.pvMorePar )
198 {
199 for( auto& pExprList: *aVar.pvMorePar )
200 {
201 pExprList->Gen(rGen);
203 }
204 }
205}
206
207// Create an Argv-Table
208// The first element remain available for return value etc.
209// See as well SbiProcDef::SbiProcDef() in symtbl.cxx
210
212{
213 if( aData.empty() )
214 return;
215
216 rGen.Gen( SbiOpcode::ARGC_ );
217 // Type adjustment at DECLARE
218
219 for( auto& pExpr: aData )
220 {
221 pExpr->Gen();
222 if( !pExpr->GetName().isEmpty() )
223 {
224 // named arg
225 sal_uInt16 nSid = rGen.GetParser()->aGblStrings.Add( pExpr->GetName() );
226 rGen.Gen( SbiOpcode::ARGN_, nSid );
227
228 /* TODO: Check after Declare concept change
229 // From 1996-01-10: Type adjustment at named -> search suitable parameter
230 if( pProc )
231 {
232 // For the present: trigger an error
233 pParser->Error( ERRCODE_BASIC_NO_NAMED_ARGS );
234
235 // Later, if Named Args at DECLARE is possible
236 //for( sal_uInt16 i = 1 ; i < nParAnz ; i++ )
237 //{
238 // SbiSymDef* pDef = pPool->Get( i );
239 // const String& rName = pDef->GetName();
240 // if( rName.Len() )
241 // {
242 // if( pExpr->GetName().ICompare( rName )
243 // == COMPARE_EQUAL )
244 // {
245 // pParser->aGen.Gen( ARGTYP_, pDef->GetType() );
246 // break;
247 // }
248 // }
249 //}
250 }
251 */
252 }
253 else
254 {
255 rGen.Gen( SbiOpcode::ARGV_ );
256 }
257 }
258}
259
261{
262 // special treatment for WITH
263 // If pExpr == .-term in With, approximately Gen for Basis-Object
264 pExpr->Gen( pParser->aGen, eRecMode );
265 if( bByVal )
266 {
268 }
269 if( bBased )
270 {
271 sal_uInt16 uBase = pParser->nBase;
272 if( pParser->IsCompatible() )
273 {
274 uBase |= 0x8000; // #109275 Flag compatibility
275 }
278 }
279}
280
281/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
SbiParser * GetParser()
Definition: codegen.hxx:38
sal_uInt32 Gen(SbiOpcode)
Definition: codegen.cxx:88
short GetSize() const
Definition: expr.hxx:100
void Gen(SbiCodeGen &rGen)
Definition: exprgen.cxx:211
std::vector< std::unique_ptr< SbiExpression > > aData
Definition: expr.hxx:89
bool IsBracket() const
Definition: expr.hxx:98
sal_uInt16 nTypeStrId
Definition: expr.hxx:111
SbxDataType eType
Definition: expr.hxx:120
bool IsConstant() const
Definition: expr.hxx:144
std::unique_ptr< SbiExprNode > pLeft
Definition: expr.hxx:116
SbiNodeType eNodeType
Definition: expr.hxx:119
SbiToken eTok
Definition: expr.hxx:121
std::unique_ptr< SbiExprNode > pRight
Definition: expr.hxx:117
void GenElement(SbiCodeGen &, SbiOpcode)
Definition: exprgen.cxx:177
void Gen(SbiCodeGen &rGen, RecursiveMode eRecMode=UNDEFINED)
Definition: exprgen.cxx:64
SbxDataType GetType() const
Definition: expr.hxx:151
SbiExprNode * pWithParent
Definition: expr.hxx:118
double nVal
Definition: expr.hxx:112
bool IsOperand() const
Definition: expr.hxx:127
OUString aStrVal
Definition: expr.hxx:115
SbVar aVar
Definition: expr.hxx:113
void Gen(RecursiveMode eRecMode=UNDEFINED)
Definition: exprgen.cxx:260
bool bBased
Definition: expr.hxx:174
std::unique_ptr< SbiExprNode > pExpr
Definition: expr.hxx:171
bool bByVal
Definition: expr.hxx:176
SbiParser * pParser
Definition: expr.hxx:170
bool bClassModule
Definition: parser.hxx:72
SbiStringPool aGblStrings
Definition: parser.hxx:63
short nBase
Definition: parser.hxx:70
SbiCodeGen aGen
Definition: parser.hxx:68
bool IsCompatible() const
Definition: scanner.hxx:75
short Add(const OUString &)
Definition: symtbl.cxx:51
SbiSymScope GetScope() const
Definition: symtbl.cxx:394
sal_uInt16 GetPos() const
Definition: symtbl.hxx:123
virtual SbiProcDef * GetProcDef()
Definition: symtbl.cxx:310
bool IsGlobal() const
Definition: symtbl.hxx:148
sal_uInt16 GetId() const
Definition: symtbl.hxx:120
bool IsStatic() const
Definition: symtbl.hxx:145
void Error(ErrCode c)
Definition: token.hxx:123
UNDEFINED
RecursiveMode
Definition: expr.hxx:82
@ FORCE_CALL
Definition: expr.hxx:84
@ SbxTYPEOF
Definition: expr.hxx:75
@ SbxNEW
Definition: expr.hxx:77
const OpTable aOpTable[]
Definition: exprgen.cxx:37
void * p
sal_Int16 nId
SbiOpcode
Definition: opcodes.hxx:25
#define ERRCODE_BASIC_INTERNAL_ERROR
Definition: sberrors.hxx:33
@ SbxEMPTY
Definition: sbxdef.hxx:38
@ SbxSTRING
Definition: sbxdef.hxx:46
SbiExprListVector * pvMorePar
Definition: expr.hxx:44
SbiSymDef * pDef
Definition: expr.hxx:42
SbiExprList * pPar
Definition: expr.hxx:43
@ SbPARAM
Definition: symtbl.hxx:32
@ SbRTL
Definition: symtbl.hxx:32
SbiToken
Definition: token.hxx:30
@ NOT
Definition: token.hxx:74
@ MUL
Definition: token.hxx:71
@ GT
Definition: token.hxx:73
@ MOD
Definition: token.hxx:72
@ CAT
Definition: token.hxx:75
@ LT
Definition: token.hxx:73
@ NE
Definition: token.hxx:73
@ GE
Definition: token.hxx:73
@ LE
Definition: token.hxx:73
@ NIL
Definition: token.hxx:31
@ IS
Definition: token.hxx:75
@ EQV
Definition: token.hxx:74
@ IMP
Definition: token.hxx:75
@ DIV
Definition: token.hxx:72
@ AND
Definition: token.hxx:74
@ PLUS
Definition: token.hxx:72
@ OR
Definition: token.hxx:74
@ EQ
Definition: token.hxx:73
@ LIKE
Definition: token.hxx:75
@ XOR
Definition: token.hxx:74
@ EXPON
Definition: token.hxx:71
@ MINUS
Definition: token.hxx:72
@ NEG
Definition: token.hxx:71
@ IDIV
Definition: token.hxx:72