1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <basic/sberrors.hxx>
22 #include <codegen.hxx>
26 // Transform table for token operators and opcodes
31 SbiToken eTok
; // Token
32 SbiOpcode eOp
; // Opcode
37 const OpTable aOpTable
[] = {
38 { EXPON
,SbiOpcode::EXP_
},
39 { MUL
, SbiOpcode::MUL_
},
40 { DIV
, SbiOpcode::DIV_
},
41 { IDIV
, SbiOpcode::IDIV_
},
42 { MOD
, SbiOpcode::MOD_
},
43 { PLUS
, SbiOpcode::PLUS_
},
44 { MINUS
,SbiOpcode::MINUS_
},
45 { EQ
, SbiOpcode::EQ_
},
46 { NE
, SbiOpcode::NE_
},
47 { LE
, SbiOpcode::LE_
},
48 { GE
, SbiOpcode::GE_
},
49 { LT
, SbiOpcode::LT_
},
50 { GT
, SbiOpcode::GT_
},
51 { AND
, SbiOpcode::AND_
},
52 { OR
, SbiOpcode::OR_
},
53 { XOR
, SbiOpcode::XOR_
},
54 { EQV
, SbiOpcode::EQV_
},
55 { IMP
, SbiOpcode::IMP_
},
56 { NOT
, SbiOpcode::NOT_
},
57 { NEG
, SbiOpcode::NEG_
},
58 { CAT
, SbiOpcode::CAT_
},
59 { LIKE
, SbiOpcode::LIKE_
},
60 { IS
, SbiOpcode::IS_
},
61 { NIL
, SbiOpcode::NOP_
}};
63 // Output of an element
64 void SbiExprNode::Gen( SbiCodeGen
& rGen
, RecursiveMode eRecMode
)
73 rGen
.Gen( SbiOpcode::EMPTY_
);
76 nStringId
= rGen
.GetParser()->aGblStrings
.Add( aStrVal
);
77 rGen
.Gen( SbiOpcode::SCONST_
, nStringId
);
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
);
88 else if( IsOperand() )
90 SbiExprNode
* pWithParent_
= nullptr;
92 if( aVar
.pDef
->GetScope() == SbPARAM
)
94 eOp
= SbiOpcode::PARAM_
;
95 if( aVar
.pDef
->GetPos() == 0 )
97 bool bTreatFunctionAsParam
= true;
98 if( eRecMode
== FORCE_CALL
)
100 bTreatFunctionAsParam
= false;
102 else if( eRecMode
== UNDEFINED
)
104 if( aVar
.pPar
&& aVar
.pPar
->IsBracket() )
106 bTreatFunctionAsParam
= false;
109 if( !bTreatFunctionAsParam
)
111 eOp
= aVar
.pDef
->IsGlobal() ? SbiOpcode::FIND_G_
: SbiOpcode::FIND_
;
115 // special treatment for WITH
116 else if( (pWithParent_
= pWithParent
) != nullptr )
118 eOp
= SbiOpcode::ELEM_
; // .-Term in WITH
122 eOp
= ( aVar
.pDef
->GetScope() == SbRTL
) ? SbiOpcode::RTL_
:
123 (aVar
.pDef
->IsGlobal() ? SbiOpcode::FIND_G_
: SbiOpcode::FIND_
);
126 if( eOp
== SbiOpcode::FIND_
)
129 SbiProcDef
* pProc
= aVar
.pDef
->GetProcDef();
130 if ( rGen
.GetParser()->bClassModule
)
132 eOp
= SbiOpcode::FIND_CM_
;
134 else if ( aVar
.pDef
->IsStatic() || (pProc
&& pProc
->IsStatic()) )
136 eOp
= SbiOpcode::FIND_STATIC_
;
140 if (pWithParent_
!= nullptr)
141 pWithParent_
->Gen(rGen
);
143 for( SbiExprNode
* p
= this; p
; p
= p
->aVar
.pNext
)
145 p
->GenElement( rGen
, eOp
);
146 eOp
= SbiOpcode::ELEM_
;
149 else if( eNodeType
== SbxTYPEOF
)
152 rGen
.Gen( SbiOpcode::TESTCLASS_
, nTypeStrId
);
154 else if( eNodeType
== SbxNEW
)
156 rGen
.Gen( SbiOpcode::CREATE_
, 0, nTypeStrId
);
165 for( const OpTable
* p
= aOpTable
; p
->eTok
!= NIL
; p
++ )
167 if( p
->eTok
== eTok
)
169 rGen
.Gen( p
->eOp
); break;
175 // Output of an operand element
177 void SbiExprNode::GenElement( SbiCodeGen
& rGen
, SbiOpcode eOp
)
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
, u
"Opcode"_ustr
);
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
187 sal_uInt16 nId
= ( eOp
== SbiOpcode::PARAM_
) ? pDef
->GetPos() : pDef
->GetId();
188 // Build a parameter list
189 if( aVar
.pPar
&& aVar
.pPar
->GetSize() )
192 aVar
.pPar
->Gen(rGen
);
195 rGen
.Gen( eOp
, nId
, sal::static_int_cast
< sal_uInt16
>( GetType() ) );
199 for( auto& pExprList
: *aVar
.pvMorePar
)
201 pExprList
->Gen(rGen
);
202 rGen
.Gen( SbiOpcode::ARRAYACCESS_
);
207 // Create an Argv-Table
208 // The first element remain available for return value etc.
209 // See as well SbiProcDef::SbiProcDef() in symtbl.cxx
211 void SbiExprList::Gen(SbiCodeGen
& rGen
)
216 rGen
.Gen( SbiOpcode::ARGC_
);
217 // Type adjustment at DECLARE
219 for( auto& pExpr
: aData
)
222 if( !pExpr
->GetName().isEmpty() )
225 sal_uInt16 nSid
= rGen
.GetParser()->aGblStrings
.Add( pExpr
->GetName() );
226 rGen
.Gen( SbiOpcode::ARGN_
, nSid
);
228 /* TODO: Check after Declare concept change
229 // From 1996-01-10: Type adjustment at named -> search suitable parameter
232 // For the present: trigger an error
233 pParser->Error( ERRCODE_BASIC_NO_NAMED_ARGS );
235 // Later, if Named Args at DECLARE is possible
236 //for( sal_uInt16 i = 1 ; i < nParAnz ; i++ )
238 // SbiSymDef* pDef = pPool->Get( i );
239 // const String& rName = pDef->GetName();
242 // if( pExpr->GetName().ICompare( rName )
243 // == COMPARE_EQUAL )
245 // pParser->aGen.Gen( ARGTYP_, pDef->GetType() );
255 rGen
.Gen( SbiOpcode::ARGV_
);
260 void SbiExpression::Gen( RecursiveMode eRecMode
)
262 // special treatment for WITH
263 // If pExpr == .-term in With, approximately Gen for Basis-Object
264 pExpr
->Gen( pParser
->aGen
, eRecMode
);
267 pParser
->aGen
.Gen( SbiOpcode::BYVAL_
);
271 sal_uInt16 uBase
= pParser
->nBase
;
272 if( pParser
->IsCompatible() )
274 uBase
|= 0x8000; // #109275 Flag compatibility
276 pParser
->aGen
.Gen( SbiOpcode::BASED_
, uBase
);
277 pParser
->aGen
.Gen( SbiOpcode::ARGV_
);
281 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */