summaryrefslogtreecommitdiff
path: root/basic/source/comp/exprgen.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'basic/source/comp/exprgen.cxx')
-rw-r--r--basic/source/comp/exprgen.cxx297
1 files changed, 297 insertions, 0 deletions
diff --git a/basic/source/comp/exprgen.cxx b/basic/source/comp/exprgen.cxx
new file mode 100644
index 000000000000..89520832ff67
--- /dev/null
+++ b/basic/source/comp/exprgen.cxx
@@ -0,0 +1,297 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_basic.hxx"
+
+#include "sbcomp.hxx"
+#include "expr.hxx"
+
+// Umsetztabelle fuer Token-Operatoren und Opcodes
+
+typedef struct {
+ SbiToken eTok; // Token
+ SbiOpcode eOp; // Opcode
+} OpTable;
+
+static OpTable aOpTable [] = {
+ { EXPON,_EXP },
+ { MUL, _MUL },
+ { DIV, _DIV },
+ { IDIV, _IDIV },
+ { MOD, _MOD },
+ { PLUS, _PLUS },
+ { MINUS,_MINUS },
+ { EQ, _EQ },
+ { NE, _NE },
+ { LE, _LE },
+ { GE, _GE },
+ { LT, _LT },
+ { GT, _GT },
+ { AND, _AND },
+ { OR, _OR },
+ { XOR, _XOR },
+ { EQV, _EQV },
+ { IMP, _IMP },
+ { NOT, _NOT },
+ { NEG, _NEG },
+ { CAT, _CAT },
+ { LIKE, _LIKE },
+ { IS, _IS },
+ { NIL, _NOP }};
+
+// Ausgabe eines Elements
+void SbiExprNode::Gen( RecursiveMode eRecMode )
+{
+ if( IsConstant() )
+ {
+ switch( GetType() )
+ {
+ case SbxEMPTY: pGen->Gen( _EMPTY ); break;
+ case SbxINTEGER: pGen->Gen( _CONST, (short) nVal ); break;
+ case SbxSTRING:
+ {
+ USHORT nStringId = pGen->GetParser()->aGblStrings.Add( aStrVal, TRUE );
+ pGen->Gen( _SCONST, nStringId ); break;
+ }
+ default:
+ {
+ USHORT nStringId = pGen->GetParser()->aGblStrings.Add( nVal, eType );
+ pGen->Gen( _NUMBER, nStringId );
+ }
+ }
+ }
+ else if( IsOperand() )
+ {
+ SbiExprNode* pWithParent_ = NULL;
+ SbiOpcode eOp;
+ if( aVar.pDef->GetScope() == SbPARAM )
+ {
+ eOp = _PARAM;
+ if( 0 == aVar.pDef->GetPos() )
+ {
+ bool bTreatFunctionAsParam = true;
+ if( eRecMode == FORCE_CALL )
+ {
+ bTreatFunctionAsParam = false;
+ }
+ else if( eRecMode == UNDEFINED )
+ {
+ if( aVar.pPar && aVar.pPar->IsBracket() )
+ bTreatFunctionAsParam = false;
+ }
+ if( !bTreatFunctionAsParam )
+ eOp = aVar.pDef->IsGlobal() ? _FIND_G : _FIND;
+ }
+ }
+ // AB: 17.12.1995, Spezialbehandlung fuer WITH
+ else if( (pWithParent_ = GetWithParent()) != NULL )
+ {
+ eOp = _ELEM; // .-Ausdruck in WITH
+ }
+ else
+ {
+ SbiProcDef* pProc = aVar.pDef->GetProcDef();
+ // per DECLARE definiert?
+ if( pProc && pProc->GetLib().Len() )
+ eOp = pProc->IsCdecl() ? _CALLC : _CALL;
+ else
+ eOp = ( aVar.pDef->GetScope() == SbRTL ) ? _RTL :
+ (aVar.pDef->IsGlobal() ? _FIND_G : _FIND);
+ }
+
+ if( eOp == _FIND )
+ {
+
+ SbiProcDef* pProc = aVar.pDef->GetProcDef();
+ if ( pGen->GetParser()->bClassModule )
+ eOp = _FIND_CM;
+ else if ( aVar.pDef->IsStatic() || (pProc && pProc->IsStatic()) )
+ {
+ eOp = _FIND_STATIC;
+ }
+ }
+ for( SbiExprNode* p = this; p; p = p->aVar.pNext )
+ {
+ if( p == this && pWithParent_ != NULL )
+ pWithParent_->Gen();
+ p->GenElement( eOp );
+ eOp = _ELEM;
+ }
+ }
+ else if( IsTypeOf() )
+ {
+ pLeft->Gen();
+ pGen->Gen( _TESTCLASS, nTypeStrId );
+ }
+ else
+ {
+ pLeft->Gen();
+ if( pRight )
+ pRight->Gen();
+ for( OpTable* p = aOpTable; p->eTok != NIL; p++ )
+ {
+ if( p->eTok == eTok )
+ {
+ pGen->Gen( p->eOp ); break;
+ }
+ }
+ }
+}
+
+// Ausgabe eines Operanden-Elements
+
+void SbiExprNode::GenElement( SbiOpcode eOp )
+{
+#ifdef DBG_UTIL
+ if( (eOp < _RTL || eOp > _CALLC) && eOp != _FIND_G && eOp != _FIND_CM )
+ pGen->GetParser()->Error( SbERR_INTERNAL_ERROR, "Opcode" );
+#endif
+ SbiSymDef* pDef = aVar.pDef;
+ // Das ID ist entweder die Position oder das String-ID
+ // Falls das Bit 0x8000 gesetzt ist, hat die Variable
+ // eine Parameterliste.
+ USHORT nId = ( eOp == _PARAM ) ? pDef->GetPos() : pDef->GetId();
+ // Parameterliste aufbauen
+ if( aVar.pPar && aVar.pPar->GetSize() )
+ {
+ nId |= 0x8000;
+ aVar.pPar->Gen();
+ }
+
+ SbiProcDef* pProc = aVar.pDef->GetProcDef();
+ // per DECLARE definiert?
+ if( pProc )
+ {
+ // Dann evtl. einen LIB-Befehl erzeugen
+ if( pProc->GetLib().Len() )
+ pGen->Gen( _LIB, pGen->GetParser()->aGblStrings.Add( pProc->GetLib() ) );
+ // und den Aliasnamen nehmen
+ if( pProc->GetAlias().Len() )
+ nId = ( nId & 0x8000 ) | pGen->GetParser()->aGblStrings.Add( pProc->GetAlias() );
+ }
+ pGen->Gen( eOp, nId, sal::static_int_cast< UINT16 >( GetType() ) );
+
+ if( aVar.pvMorePar )
+ {
+ SbiExprListVector* pvMorePar = aVar.pvMorePar;
+ SbiExprListVector::iterator it;
+ for( it = pvMorePar->begin() ; it != pvMorePar->end() ; ++it )
+ {
+ SbiExprList* pExprList = *it;
+ pExprList->Gen();
+ pGen->Gen( _ARRAYACCESS );
+ }
+ }
+}
+
+// Erzeugen einer Argv-Tabelle
+// Das erste Element bleibt immer frei fuer Returnwerte etc.
+// Siehe auch SbiProcDef::SbiProcDef() in symtbl.cxx
+
+void SbiExprList::Gen()
+{
+ if( pFirst )
+ {
+ pParser->aGen.Gen( _ARGC );
+ // AB 10.1.96: Typ-Anpassung bei DECLARE
+ USHORT nCount = 1, nParAnz = 0;
+ SbiSymPool* pPool = NULL;
+ if( pProc )
+ {
+ pPool = &pProc->GetParams();
+ nParAnz = pPool->GetSize();
+ }
+ for( SbiExpression* pExpr = pFirst; pExpr; pExpr = pExpr->pNext,nCount++ )
+ {
+ pExpr->Gen();
+ if( pExpr->GetName().Len() )
+ {
+ // named arg
+ USHORT nSid = pParser->aGblStrings.Add( pExpr->GetName() );
+ pParser->aGen.Gen( _ARGN, nSid );
+
+ // AB 10.1.96: Typanpassung bei named -> passenden Parameter suchen
+ if( pProc )
+ {
+ // Vorerst: Error ausloesen
+ pParser->Error( SbERR_NO_NAMED_ARGS );
+
+ // Spaeter, wenn Named Args bei DECLARE moeglich
+ /*
+ for( USHORT i = 1 ; i < nParAnz ; i++ )
+ {
+ SbiSymDef* pDef = pPool->Get( i );
+ const String& rName = pDef->GetName();
+ if( rName.Len() )
+ {
+ if( pExpr->GetName().ICompare( rName )
+ == COMPARE_EQUAL )
+ {
+ pParser->aGen.Gen( _ARGTYP, pDef->GetType() );
+ break;
+ }
+ }
+ }
+ */
+ }
+ }
+ else
+ {
+ pParser->aGen.Gen( _ARGV );
+
+ // Funktion mit DECLARE -> Typ-Anpassung
+ if( pProc && nCount < nParAnz )
+ {
+ SbiSymDef* pDef = pPool->Get( nCount );
+ USHORT nTyp = sal::static_int_cast< USHORT >(
+ pDef->GetType() );
+ // Zusätzliches Flag für BYVAL einbauen
+ if( pDef->IsByVal() )
+ nTyp |= 0x8000;
+ pParser->aGen.Gen( _ARGTYP, nTyp );
+ }
+ }
+ }
+ }
+}
+
+void SbiExpression::Gen( RecursiveMode eRecMode )
+{
+ // AB: 17.12.1995, Spezialbehandlung fuer WITH
+ // Wenn pExpr == .-Ausdruck in With, zunaechst Gen fuer Basis-Objekt
+ pExpr->Gen( eRecMode );
+ if( bBased )
+ {
+ USHORT uBase = pParser->nBase;
+ if( pParser->IsCompatible() )
+ uBase |= 0x8000; // #109275 Flag compatiblity
+ pParser->aGen.Gen( _BASED, uBase );
+ pParser->aGen.Gen( _ARGV );
+ }
+}
+