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
29 SbiToken eTok
; // Token
30 SbiOpcode eOp
; // Opcode
33 static const OpTable aOpTable
[] = {
34 { EXPON
,SbiOpcode::EXP_
},
35 { MUL
, SbiOpcode::MUL_
},
36 { DIV
, SbiOpcode::DIV_
},
37 { IDIV
, SbiOpcode::IDIV_
},
38 { MOD
, SbiOpcode::MOD_
},
39 { PLUS
, SbiOpcode::PLUS_
},
40 { MINUS
,SbiOpcode::MINUS_
},
41 { EQ
, SbiOpcode::EQ_
},
42 { NE
, SbiOpcode::NE_
},
43 { LE
, SbiOpcode::LE_
},
44 { GE
, SbiOpcode::GE_
},
45 { LT
, SbiOpcode::LT_
},
46 { GT
, SbiOpcode::GT_
},
47 { AND
, SbiOpcode::AND_
},
48 { OR
, SbiOpcode::OR_
},
49 { XOR
, SbiOpcode::XOR_
},
50 { EQV
, SbiOpcode::EQV_
},
51 { IMP
, SbiOpcode::IMP_
},
52 { NOT
, SbiOpcode::NOT_
},
53 { NEG
, SbiOpcode::NEG_
},
54 { CAT
, SbiOpcode::CAT_
},
55 { LIKE
, SbiOpcode::LIKE_
},
56 { IS
, SbiOpcode::IS_
},
57 { NIL
, SbiOpcode::NOP_
}};
59 // Output of an element
60 void SbiExprNode::Gen( SbiCodeGen
& rGen
, RecursiveMode eRecMode
)
69 rGen
.Gen( SbiOpcode::EMPTY_
);
72 rGen
.Gen( SbiOpcode::CONST_
, static_cast<short>(nVal
) );
75 nStringId
= rGen
.GetParser()->aGblStrings
.Add( aStrVal
);
76 rGen
.Gen( SbiOpcode::SCONST_
, nStringId
);
79 nStringId
= rGen
.GetParser()->aGblStrings
.Add( nVal
, eType
);
80 rGen
.Gen( SbiOpcode::NUMBER_
, nStringId
);
84 else if( IsOperand() )
86 SbiExprNode
* pWithParent_
= nullptr;
88 if( aVar
.pDef
->GetScope() == SbPARAM
)
90 eOp
= SbiOpcode::PARAM_
;
91 if( aVar
.pDef
->GetPos() == 0 )
93 bool bTreatFunctionAsParam
= true;
94 if( eRecMode
== FORCE_CALL
)
96 bTreatFunctionAsParam
= false;
98 else if( eRecMode
== UNDEFINED
)
100 if( aVar
.pPar
&& aVar
.pPar
->IsBracket() )
102 bTreatFunctionAsParam
= false;
105 if( !bTreatFunctionAsParam
)
107 eOp
= aVar
.pDef
->IsGlobal() ? SbiOpcode::FIND_G_
: SbiOpcode::FIND_
;
111 // special treatment for WITH
112 else if( (pWithParent_
= pWithParent
) != nullptr )
114 eOp
= SbiOpcode::ELEM_
; // .-Term in WITH
118 eOp
= ( aVar
.pDef
->GetScope() == SbRTL
) ? SbiOpcode::RTL_
:
119 (aVar
.pDef
->IsGlobal() ? SbiOpcode::FIND_G_
: SbiOpcode::FIND_
);
122 if( eOp
== SbiOpcode::FIND_
)
125 SbiProcDef
* pProc
= aVar
.pDef
->GetProcDef();
126 if ( rGen
.GetParser()->bClassModule
)
128 eOp
= SbiOpcode::FIND_CM_
;
130 else if ( aVar
.pDef
->IsStatic() || (pProc
&& pProc
->IsStatic()) )
132 eOp
= SbiOpcode::FIND_STATIC_
;
135 for( SbiExprNode
* p
= this; p
; p
= p
->aVar
.pNext
)
137 if( p
== this && pWithParent_
!= nullptr )
139 pWithParent_
->Gen(rGen
);
141 p
->GenElement( rGen
, eOp
);
142 eOp
= SbiOpcode::ELEM_
;
145 else if( eNodeType
== SbxTYPEOF
)
148 rGen
.Gen( SbiOpcode::TESTCLASS_
, nTypeStrId
);
150 else if( eNodeType
== SbxNEW
)
152 rGen
.Gen( SbiOpcode::CREATE_
, 0, nTypeStrId
);
161 for( const OpTable
* p
= aOpTable
; p
->eTok
!= NIL
; p
++ )
163 if( p
->eTok
== eTok
)
165 rGen
.Gen( p
->eOp
); break;
171 // Output of an operand element
173 void SbiExprNode::GenElement( SbiCodeGen
& rGen
, SbiOpcode eOp
)
176 if ((eOp
< SbiOpcode::RTL_
|| eOp
> SbiOpcode::CALLC_
) && eOp
!= SbiOpcode::FIND_G_
&& eOp
!= SbiOpcode::FIND_CM_
&& eOp
!= SbiOpcode::FIND_STATIC_
)
177 rGen
.GetParser()->Error( ERRCODE_BASIC_INTERNAL_ERROR
, "Opcode" );
179 SbiSymDef
* pDef
= aVar
.pDef
;
180 // The ID is either the position or the String-ID
181 // If the bit Bit 0x8000 is set, the variable have
183 sal_uInt16 nId
= ( eOp
== SbiOpcode::PARAM_
) ? pDef
->GetPos() : pDef
->GetId();
184 // Build a parameter list
185 if( aVar
.pPar
&& aVar
.pPar
->GetSize() )
188 aVar
.pPar
->Gen(rGen
);
191 rGen
.Gen( eOp
, nId
, sal::static_int_cast
< sal_uInt16
>( GetType() ) );
195 for( auto& pExprList
: *aVar
.pvMorePar
)
197 pExprList
->Gen(rGen
);
198 rGen
.Gen( SbiOpcode::ARRAYACCESS_
);
203 // Create an Argv-Table
204 // The first element remain available for return value etc.
205 // See as well SbiProcDef::SbiProcDef() in symtbl.cxx
207 void SbiExprList::Gen(SbiCodeGen
& rGen
)
211 rGen
.Gen( SbiOpcode::ARGC_
);
212 // Type adjustment at DECLARE
214 for( auto& pExpr
: aData
)
217 if( !pExpr
->GetName().isEmpty() )
220 sal_uInt16 nSid
= rGen
.GetParser()->aGblStrings
.Add( pExpr
->GetName() );
221 rGen
.Gen( SbiOpcode::ARGN_
, nSid
);
223 /* TODO: Check after Declare concept change
224 // From 1996-01-10: Type adjustment at named -> search suitable parameter
227 // For the present: trigger an error
228 pParser->Error( ERRCODE_BASIC_NO_NAMED_ARGS );
230 // Later, if Named Args at DECLARE is possible
231 //for( sal_uInt16 i = 1 ; i < nParAnz ; i++ )
233 // SbiSymDef* pDef = pPool->Get( i );
234 // const String& rName = pDef->GetName();
237 // if( pExpr->GetName().ICompare( rName )
238 // == COMPARE_EQUAL )
240 // pParser->aGen.Gen( ARGTYP_, pDef->GetType() );
250 rGen
.Gen( SbiOpcode::ARGV_
);
256 void SbiExpression::Gen( RecursiveMode eRecMode
)
258 // special treatment for WITH
259 // If pExpr == .-term in With, approximately Gen for Basis-Object
260 pExpr
->Gen( pParser
->aGen
, eRecMode
);
263 pParser
->aGen
.Gen( SbiOpcode::BYVAL_
);
267 sal_uInt16 uBase
= pParser
->nBase
;
268 if( pParser
->IsCompatible() )
270 uBase
|= 0x8000; // #109275 Flag compatibility
272 pParser
->aGen
.Gen( SbiOpcode::BASED_
, uBase
);
273 pParser
->aGen
.Gen( SbiOpcode::ARGV_
);
277 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */