Permalink
Switch branches/tags
Nothing to show
Find file Copy path
45d2253 Mar 25, 2014
0 contributors

Users who have contributed to this file

1348 lines (1126 sloc) 40.2 KB
// ðåàëèçàöèÿ òðàíñëÿòîðà â Ñ-êîä - Translator.cpp
#pragma warning(disable: 4786)
#include <nrc.h>
using namespace NRC;
#include "Limits.h"
#include "Application.h"
#include "LexicalAnalyzer.h"
#include "Object.h"
#include "Scope.h"
#include "Class.h"
#include "Manager.h"
#include "Parser.h"
#include "Body.h"
#include "Checker.h"
#include "ExpressionMaker.h"
#include "Translator.h"
// ñ÷åò÷èê âðåìåííûõ îáúåêòîâ
int TemporaryObject::temporaryCounter = 0;
// ãåíåðèðóåò èìÿ îáëàñòè âèäèìîñòè áåç äîáàâî÷íûõ ñèìâîëîâ. Ó÷èòûâàåò
// ñëåä. îáëàñòè âèäèìîñòè: ãëîáàëüíàÿ, èìåíîâàííàÿ, êëàññîâàÿ, ôóíêöèîíàëüíàÿ (ëîêàëüíàÿ)
const string &TranslatorUtils::GenerateScopeName( const SymbolTable &scope )
{
static string rbuf;
const SymbolTable *psc = &scope;
// ïåðåõîäèì îò ëîêàëüíîé îáëàñòè âèäèìîñòè ê ôóíêöèîíàëüíîé
while( psc->IsLocalSymbolTable() )
{
psc = &static_cast<const LocalSymbolTable *>(psc)->GetParentSymbolTable();
INTERNAL_IF( psc->IsGlobalSymbolTable() );
}
for( rbuf = "";; )
{
// ïðîâåðÿåì, åñëè ôóíêöèîíàëüíàÿ, ïîäñòàâëÿåì èìÿ ôóíêöèè ê îáùåìó èìåíè
if( psc->IsFunctionSymbolTable() )
{
rbuf = static_cast<const FunctionSymbolTable *>(psc)->
GetFunction().GetName() + '_' + rbuf;
psc = &static_cast<const FunctionSymbolTable *>(psc)->GetParentSymbolTable();
}
// åñëè êëàññîâàÿ
else if( psc->IsClassSymbolTable() )
{
rbuf = static_cast<const ClassType *>(psc)->GetName() + '_' + rbuf;
psc = &static_cast<const ClassType *>(psc)->GetSymbolTableEntry();
}
// åñëè èìåíîâàííàÿ
else if( psc->IsNamespaceSymbolTable() )
{
rbuf = static_cast<const NameSpace *>(psc)->GetName() + '_' + rbuf;
psc = &static_cast<const NameSpace *>(psc)->GetSymbolTableEntry();
}
// åñëè ãëîáàëüíàÿ, âûõîäèì íè÷åãî íå äîáàâëÿÿ
else if( psc->IsGlobalSymbolTable() )
return rbuf;
// èíà÷å íåèçâåñòíàÿ
else
INTERNAL("'TranslatorUtils::GenerateScopeName' - íåèçâåñòíàÿ îáëàñòü âèäèìîñòè");
}
return rbuf; // kill warning
}
// ñãåíåðèðîâàòü èìÿ äëÿ áåçèìÿííîãî èäåíòèôèêàòîðà
string TranslatorUtils::GenerateUnnamed( )
{
static int unnamedCount = 1;
CharString dig( unnamedCount++ );
return string("unnamed") + dig.c_str();
}
// âåðíóòü ñòðîêîâûé ýêâèâàëåíò îïåðàòîðà
PCSTR TranslatorUtils::GenerateOperatorName( int op )
{
PCSTR opBuf;
switch( op )
{
case KWNEW: opBuf = "new"; break;
case -KWDELETE:
case KWDELETE: opBuf = "delete"; break;
case OC_NEW_ARRAY: opBuf = "newar"; break;
case -OC_DELETE_ARRAY:
case OC_DELETE_ARRAY: opBuf = "deletear"; break;
case OC_FUNCTION: opBuf = "fn"; break;
case OC_ARRAY: opBuf = "ar"; break;
case PLUS_ASSIGN: opBuf = "plusasgn"; break;
case MINUS_ASSIGN: opBuf = "minasgn"; break;
case MUL_ASSIGN: opBuf = "mulasgn"; break;
case DIV_ASSIGN: opBuf = "divasgn"; break;
case PERCENT_ASSIGN: opBuf = "percasgn"; break;
case LEFT_SHIFT_ASSIGN: opBuf = "leftshftasgn"; break;
case RIGHT_SHIFT_ASSIGN:opBuf = "rightshftasgn"; break;
case AND_ASSIGN: opBuf = "andasgn"; break;
case XOR_ASSIGN: opBuf = "xorasgn"; break;
case OR_ASSIGN: opBuf = "orasgn"; break;
case LEFT_SHIFT: opBuf = "lshft"; break;
case RIGHT_SHIFT: opBuf = "rshft"; break;
case LESS_EQU: opBuf = "lessequ"; break;
case GREATER_EQU: opBuf = "grequ"; break;
case EQUAL: opBuf = "equ"; break;
case NOT_EQUAL: opBuf = "notequ"; break;
case LOGIC_AND: opBuf = "logand"; break;
case LOGIC_OR: opBuf = "logor"; break;
case -INCREMENT:
case INCREMENT: opBuf = "inc"; break;
case -DECREMENT:
case DECREMENT: opBuf = "dec"; break;
case ARROW: opBuf = "arrow"; break;
case ARROW_POINT: opBuf = "arpoint"; break;
case DOT_POINT: opBuf = "dotpoint"; break;
case '+': opBuf = "plus"; break;
case '-': opBuf = "minus"; break;
case '*': opBuf = "mul"; break;
case '/': opBuf = "div"; break;
case '%': opBuf = "perc"; break;
case '^': opBuf = "xor"; break;
case '!': opBuf = "not"; break;
case '=': opBuf = "asgn"; break;
case '<': opBuf = "less"; break;
case '>': opBuf = "greater"; break;
case '&': opBuf = "and"; break;
case '|': opBuf = "or"; break;
case '~': opBuf = "inv"; break;
case ',': opBuf = "coma"; break;
default:
INTERNAL("'TranslatorUtils::GenerateOverloadOperatorName' - íåèçâåñòíûé îïåðàòîð");
break;
}
return opBuf;
}
// ñãåíåðèðîâàòü è âûâåñòè äåêëàðàöèþ, òîëüêî åñëè îíà íå typedef è íå
// ðåæèì ïðèëîæåíèÿ íå äèàãíîñòè÷íûé
void TranslatorUtils::TranslateDeclaration( const TypyziedEntity &declarator,
const PObjectInitializator &iator, bool global )
{
// åñëè íå òðåáóåòñÿ, íå ãåíåðèðóåì
if( theApp.IsDiagnostic() ||
(declarator.IsObject() &&
static_cast<const ::Object &>(declarator).GetStorageSpecifier() ==
::Object::SS_TYPEDEF) )
return;
DeclarationGenerator dgen(declarator, iator, global);
dgen.Generate();
theApp.GetGenerator().GenerateToCurrentBuffer(dgen.GetOutBuffer());
theApp.GetGenerator().FlushCurrentBuffer();
}
// òðàíñëèðîâàòü äåêëàðàöèþ êëàññà
void TranslatorUtils::TranslateClass( const ClassType &cls )
{
if( theApp.IsDiagnostic() )
return;
ClassGenerator cgen( cls );
cgen.Generate();
theApp.GetGenerator().GenerateToCurrentBuffer(cgen.GetClassBuffer());
theApp.GetGenerator().GenerateToCurrentBuffer(cgen.GetOutSideBuffer());
theApp.GetGenerator().FlushCurrentBuffer();
}
// âîçâðàùàåò true, åñëè ÷ëåí èìååò êëàññîâûé òèï
bool SMFGenegator::NeedConstructor( const DataMember &dm )
{
// åñëè íå êëàññîâûé òèï, ëèáî ñïåöèôèêàòîð õðàíåíèÿ
// óêàçûâàåò, ÷òî êîíñòðóèðîâàíèå ÷ëåíà íå òðåáóåòñÿ âíóòðè êëàññà
if( !dm.GetBaseType().IsClassType() ||
dm.GetStorageSpecifier() == ::Object::SS_STATIC ||
dm.GetStorageSpecifier() == ::Object::SS_TYPEDEF )
return false;
for( int i = 0; i<dm.GetDerivedTypeList().GetDerivedTypeCount(); i++ )
if( dm.GetDerivedTypeList().GetDerivedType(i)->
GetDerivedTypeCode() != DerivedType::DT_ARRAY )
return false;
// èíà÷å òèï êëàññîâûé è êîíñòðóêòîð íåîáõîäèì
return true;
}
// çàïîëíèòü ñïèñîê çàâèñèìûõ êëàññîâ, çàïîëíÿåòñÿ â ìåòîäå Generate
void SMFGenegator::FillDependClassList()
{
// ñíà÷àëà âñòàâëÿåì áàçîâûå êëàññû
int i = 0;
for( i = 0; i<pClass.GetBaseClassList().GetBaseClassCount(); i++ )
{
const BaseClassCharacteristic &pBase =
*pClass.GetBaseClassList().GetBaseClassCharacteristic(i);
AddDependClass( &pBase.GetPointerToClass() );
if( pBase.IsVirtualDerivation() )
haveVBC = true;
}
// ïîñëå ýòîãî çàïîëíÿåì ñïèñîê íåñòàòè÷åñêèìè (è íå òèïàìè) äàííûìè ÷ëåíàìè,
// êîòîðûå èìåþò êëàññîâûé òèï
for( i = 0; i<pClass.GetMemberList().GetClassMemberCount(); i++ )
if( const DataMember *dm = dynamic_cast<const DataMember *>(
&*pClass.GetMemberList().GetClassMember(i)) )
{
if( NeedConstructor(*dm) )
AddDependClass( static_cast<const ClassType *>(&dm->GetBaseType()) );
// óñòàíàâëèâàåì ôëàã åñëè â êëàññå åñòü îáúåêòû òðåáóþùèå
// ÿâíîé èíèöèàëèçàöèÿ
if( (dm->GetStorageSpecifier() != ::Object::SS_STATIC &&
dm->GetStorageSpecifier() != ::Object::SS_TYPEDEF) &&
(dm->GetDerivedTypeList().IsReference() ||
ExpressionMakerUtils::IsConstant(*dm)) )
explicitInit = true;
}
}
// ìåòîä ïðîõîäèò ïî ñïèñêó çàâèñèìûõ êëàññîâ è ïðîâåðÿåò,
// ÿâëÿåòñÿ ëè äîñòóïíûì, îäíîçíà÷íûì è ïðèñóòñòâóåò ëè âîîáùå
// ñïåöèàëüíûé ìåòîä. Ñïåöèàëüíûé ìåòîä ïîëó÷àåì ÷åðåç óê-ëü íà ôóíêöèþ
// ÷ëåí
bool SMFGenegator::CanGenerate( const SMFManagerList &sml,
const SMFManager::SmfPair &(SMFManager::*GetMethod)() const ) const
{
// ïðîâåðÿåì, êàæäûé êëàññ â ñïèñêå
for( SMFManagerList::const_iterator p = sml.begin(); p != sml.end(); p++ )
{
const SMFManager::SmfPair &smp = (*p.*GetMethod)();
// ïðîâåðÿåì ñíà÷àëà ÷òîáû ìåòîä áûë îáúÿâëåí (first != NULL)
// è îäíîçíà÷åí (second == false)
if( !smp.first || smp.second )
return false;
// â ïîñëåäíþþ î÷åðåäü ïðîâåðÿåì äîñòóïíîñòü ìåòîäà
if( !AccessControlChecker( pClass, static_cast<const ClassType&>(
smp.first->GetSymbolTableEntry()), *smp.first ).IsAccessible() )
return false;
}
return true;
}
// âîçâðàùàåò true, åñëè ìåòîä ìîæåò áûòü ñãåíåðèðîâàí êàê òðèâèàëüíûé.
// Âûâîä äåëÿåòñÿ íà îñíîâå ñïèñêà çàâèñèìûõ êëàññîâ è ïîëèìîðôíîñòè ñîáñòâåííîãî
SMFGenegator::DependInfo SMFGenegator::GetDependInfo( const SMFManagerList &sml,
const SMFManager::SmfPair &(SMFManager::*GetMethod)() const ) const
{
DependInfo di;
// ïðîâåðÿåì, êàæäûé êëàññ â ñïèñêå
for( SMFManagerList::const_iterator p = sml.begin(); p != sml.end(); p++ )
{
const Method &meth = *(*p.*GetMethod)().first;
INTERNAL_IF( !&meth );
if( !meth.IsTrivial() )
di.trivial = false;
if( !meth.GetFunctionPrototype().GetParametrList().IsEmpty() &&
!meth.GetFunctionPrototype().GetParametrList().GetFunctionParametr(0)->IsConst() )
di.paramIsConst = false;
}
// äëÿ òðèâèàëüíîñòè òàêæå òðåáóåòñÿ, ÷òîáû ó êëàññ íå áûë ïîëèìîðôíûì,
// ò.å. îòñóòñòâîâàëà âèðòóàëüíàÿ òàáëèöà
di.trivial = di.trivial && !pClass.IsPolymorphic() && !haveVBC;
return di;
}
// âåðíóòü true, åñëè ìåòîä òðåáóåòñÿ îáúÿâèòü âèðòóàëüíûì
bool SMFGenegator::IsDeclareVirtual(const SMFManagerList &sml,
const SMFManager::SmfPair &(SMFManager::*GetMethod)() const ) const
{
const BaseClassList &bcl = pClass.GetBaseClassList();
int i = 0;
for( SMFManagerList::const_iterator p = sml.begin();
i<bcl.GetBaseClassCount(); i++, p++ )
{
INTERNAL_IF( p == sml.end() );
if( (*p.*GetMethod)().first->IsVirtual() )
return true;
}
return false;
}
// ìåòîä âîçâðàùàåò ñïèñîê ïðîèçâîäíûõ òèïîâ ñ ôóíêèåé áåç ïàðàìåòðîâ
const DerivedTypeList &SMFGenegator::MakeDTL0() const
{
static FunctionParametrList fpl;
static FunctionThrowTypeList fttl;
static PDerivedType pfn = new FunctionPrototype(false, false, fpl, fttl, true, false);
static DerivedTypeList dtl;
if( dtl.IsEmpty() )
dtl.AddDerivedType( pfn );
return dtl;
}
// ìåòîä âîçâðàùàåò ñïèñîê ïðîèçâîäíûõ òèïîâ ñ ôóíêèåé ó êîòîðîé
// â ïàðàìåòðå êîíñòàíòíûé èëè íå êîíñòàíòàÿ ññûëêà íà ýòîò êëàññ
// è âîçâðàùàåìûì òèïîì ññûëêîé
const DerivedTypeList &SMFGenegator::MakeDTL1( bool isConst ) const
{
static FunctionParametrList fpl;
// ñîçäàåì ïàðàìåòð
static DerivedTypeList prmDtl;
static PDerivedType ref = new Reference;
if( prmDtl.IsEmpty() )
prmDtl.AddDerivedType(ref);
// âñòàâëÿåì ïàðàìåòð â ñïèñîê
fpl.ClearFunctionParametrList();
fpl.AddFunctionParametr( new Parametr(&pClass, isConst, false, prmDtl, "src",
&pClass, NULL, false) );
// ñîçäàåì ïðîèçâîäíûé òèï ôóíêöèè
static FunctionThrowTypeList fttl;
static DerivedTypeList dtl;
dtl.ClearDerivedTypeList();
dtl.AddDerivedType( new FunctionPrototype(false, false, fpl, fttl, true, false) );
dtl.AddDerivedType( new Reference );
return dtl;
}
// ïîñòðîèòü êîíñòðóêòîð ïî óìîë÷àíèþ
ConstructorMethod *SMFGenegator::MakeDefCtor( bool trivial ) const
{
CharString name("."); // èìÿ êîíñòðóêòîðà íà÷èíàåòñÿ âñåãäà ñ òî÷êè
name += pClass.GetName().c_str();
DerivedTypeList dtl = MakeDTL0();
dtl.AddDerivedType( new Reference );
return new ConstructorMethod( name, &pClass, &pClass,
false, false, dtl, true, // inline - true
Function::SS_NONE, Function::CC_NON, ClassMember::AS_PUBLIC, false,
trivial ? ConstructorMethod::DT_TRIVIAL : ConstructorMethod::DT_IMPLICIT );
}
// ïîñòðîèòü êîíñòðóêòîð êîïèðîâàíèÿ
ConstructorMethod *SMFGenegator::MakeCopyCtor( bool trivial, bool isConst ) const
{
CharString name("."); // èìÿ êîíñòðóêòîðà íà÷èíàåòñÿ âñåãäà ñ òî÷êè
name += pClass.GetName().c_str();
return new ConstructorMethod( name, &pClass, &pClass,
false, false, MakeDTL1(isConst), true, // inline - true
Function::SS_NONE, Function::CC_NON, ClassMember::AS_PUBLIC, false,
trivial ? Method::DT_TRIVIAL : Method::DT_IMPLICIT );
}
// ïîñòðîèòü äåñòðóêòîð
Method *SMFGenegator::MakeDtor( bool trivial, bool isVirtual ) const
{
CharString name("~");
name += pClass.GetName().c_str();
return new Method( name, &pClass,
(BaseType *)&ImplicitTypeManager(KWVOID).GetImplicitType(), false, false, MakeDTL0(),
true, Function::SS_NONE, Function::CC_NON, ClassMember::AS_PUBLIC, false,
isVirtual, true, trivial ? Method::DT_TRIVIAL : Method::DT_IMPLICIT );
}
// ïîñòðîèòü îïåðàòîð ïðèñâàèâàíèÿ
ClassOverloadOperator *SMFGenegator::MakeCopyOperator(
Method::DT dt, bool isConst, bool isVirtual ) const
{
return new ClassOverloadOperator("operator =", &pClass, &pClass, false, false,
MakeDTL1(isConst), true, Function::SS_NONE, Function::CC_NON, ClassMember::AS_PUBLIC,
false, isVirtual, '=', "=", dt);
}
// âûâîäèò îòëàäî÷íóþ èíôîðìàöèþ ïî ìåòîäó
void SMFGenegator::DebugMethod( const Method &meth )
{
string outs = meth.GetTypyziedEntityName().c_str();
if( meth.IsVirtual() )
outs = "virtual " + outs;
if( meth.IsTrivial() )
outs += ": trivial";
cout << "* " << outs << endl;
}
// ìåòîä ãåíåðèðóåò äëÿ êëàññà ñïåöèàëüíûå ôóíêöèè ÷ëåíû, åñëè
// ýòî íåîáõîäèìî
void SMFGenegator::Generate()
{
// ïðîâåðÿåì, åñëè íàì íå íóæíî íè÷åãî ãåíåðèðîâàòü, âûõîäèì
if( !pClass.GetConstructorList().empty() &&
smfManager.GetCopyConstructor().first &&
smfManager.GetDestructor().first &&
smfManager.GetCopyOperator().first )
return;
// èíà÷å çàïîëíÿåì ñïèñîê çàâèñèìûõ êëàññîâ òåêóùåãî êëàññà
FillDependClassList();
// ïîñëå çàïîëíåíèÿ ñïèñêà çàâèñèìûõ êëàññîâ, ôîðìèðóåì íà åãî
// îñíîâå ñïèñîê ìåíåäæåðîâ ýòèõ êëàññîâ
SMFManagerList dependClsManagers;
for( ClassTypeList::const_iterator p = dependClsList.begin();
p != dependClsList.end(); p++ )
dependClsManagers.push_back( SMFManager(**p) );
// ïðîâåðÿåì, íóæåí ëè íàì êîíñòðóêòîð ïî óìîë÷àíèþ,
// â ñëó÷àå åñëè êîíñòðóêòîðîâ íå îáúÿâëåíî, ïðîäîëæàåì ãåíåðàöèþ
if( pClass.GetConstructorList().empty() )
{
// ïðîâåðÿåì, ìîæíî ëè ñãåíåðèðîâàòü ê-îð ïî óìîë÷àíèþ äëÿ íàøåãî êëàññà
if( CanGenerate(dependClsManagers, &SMFManager::GetDefaultConstructor) && !explicitInit )
pClass.InsertSymbol( MakeDefCtor(
GetDependInfo(dependClsManagers, &SMFManager::GetDefaultConstructor).trivial) );
}
// åñëè êîïèðóþùèé êîíñòðóêòîð íå ñãåíåðèðîâàí, ãåíåðèðóåì
if( smfManager.GetCopyConstructor().first == NULL )
{
if( CanGenerate(dependClsManagers, &SMFManager::GetCopyConstructor) && !explicitInit )
{
DependInfo di = GetDependInfo(dependClsManagers, &SMFManager::GetCopyConstructor);
pClass.InsertSymbol( MakeCopyCtor(di.trivial, di.paramIsConst) );
}
}
// åñëè íåîáõ. ñãåíåðèðîâàòü äåñòðóêòîð
if( smfManager.GetDestructor().first == NULL )
{
if( CanGenerate(dependClsManagers, &SMFManager::GetDestructor) )
{
DependInfo di = GetDependInfo(dependClsManagers, &SMFManager::GetDestructor);
bool isVirtual = IsDeclareVirtual(dependClsManagers, &SMFManager::GetDestructor);
pClass.InsertSymbol( MakeDtor(di.trivial, isVirtual) );
}
}
// åñëè íåîáõ. ñãåíåðèðîâàòü îïåðàòîð ïðèñâàèâàíèÿ
if( smfManager.GetCopyOperator().first == NULL )
{
// ïîìèìî ñòàíäàðòíûõ ïðîâåðîê, òàêæå ïðîâåðÿåì, ÷òîáû â êëàññå
// íå áûëî ññûëîê è êîíñòàíòíûõ îáúåêòîâ.  ýòîì ñëó÷àå îïåðàòîð
// êîïèðîâàíèÿ íå ãåíåðèðóåòñÿ
if( CanGenerate(dependClsManagers, &SMFManager::GetCopyOperator) && !explicitInit )
{
DependInfo di = GetDependInfo(dependClsManagers, &SMFManager::GetCopyOperator);
bool isVirtual = IsDeclareVirtual(dependClsManagers, &SMFManager::GetCopyOperator);
pClass.InsertSymbol( MakeCopyOperator( (di.trivial ?
Method::DT_TRIVIAL : Method::DT_IMPLICIT), di.paramIsConst, isVirtual) );
}
// èíà÷å íàì âñå ðàâíî ñëåäóåò ñãåíåðèðîâàòü îïåðàòîð, íî ïîìåòèòü
// åãî êàê íåäîñòóïíûé
else
pClass.InsertSymbol( MakeCopyOperator(Method::DT_UNAVAIBLE, false, false) );
}
}
// ñãåíåðèðîâàòü ñïåöèàëüíûå ôóíêöèè ÷ëåíû, êîòîðûå íå çàäàíû
// ÿâíî ïîëüçîâàòåëåì
void ClassParserImpl::GenerateSMF()
{
SMFGenegator(*clsType).Generate();
}
// ñãåíåðèðîâàòü Ñ-òèï â âûõîäíîé áóôåð
void CTypePrinter::Generate( )
{
BaseType::BT bt = type.GetBaseType().GetBaseTypeCode();
// const - èãíîðèðóåì, volatile îñòàâëÿåì
if( type.IsVolatile() )
baseType = "volatile ";
// åñëè áàçîâûé òèï âñòðîåííûé, ïå÷àòàåì åãî. bool â íà÷àëå ïðîãðàììû
// ïîäêëþ÷àåòñÿ ÷åðåç ôàéë stdbool.h
if( bt == BaseType::BT_BOOL || bt == BaseType::BT_CHAR ||
bt == BaseType::BT_WCHAR_T || bt == BaseType::BT_INT ||
bt == BaseType::BT_FLOAT || bt == BaseType::BT_DOUBLE ||
bt == BaseType::BT_VOID )
baseType += ImplicitTypeManager(type.GetBaseType()).GetImplicitTypeName().c_str();
// èíà÷å ïå÷àòàåì èìÿ êëàññà
else
{
INTERNAL_IF( bt != BaseType::BT_CLASS &&
bt != BaseType::BT_STRUCT &&
bt != BaseType::BT_ENUM &&
bt != BaseType::BT_UNION );
// åñëè ïåðå÷èñëåíèå, çàìåíÿåì íà int
if( bt == BaseType::BT_ENUM )
baseType += "int";
// èíà÷å ñòðóêòóðà èëè îáúåäèíåíèå
else
{
baseType += (bt == BaseType::BT_UNION ? "union " : "struct ");
// ïðèáàâëÿåì Ñ-èìÿ. Ó÷èòûâàåì, ÷òî Ñ-èìÿ ñãåíåðèðîâàíî â ëþáîì ñëó÷àå
baseType += static_cast<const ClassType &>(type.GetBaseType()).GetC_Name();
}
}
// åñëè èìååì êîíñòðóêòîð, êîíñòðóêòîð âîçâðàùàåò óêàçàòåëü íà ïåðåäàâàåìûé
// îáúåêò. Ñîîòâ. â êàæäîì êîíñòðóêòîðå ñëåäóåò äîáàâèòü "return this;"
// â êîíöå òåëà è òàì ãäå îïåðàöèÿ return
if( type.IsFunction() && static_cast<const Function &>(type).IsClassMember() &&
static_cast<const Method &>(type).IsConstructor() )
baseType += " *";
if( type.GetDerivedTypeList().GetDerivedTypeCount() != 0 )
{
string dtlBuf;
int ix = 0;
bool namePrint = id == NULL;
PrintPointer(dtlBuf, ix, namePrint);
outBuffer = baseType + ' ' + dtlBuf;
}
else if( id != NULL )
outBuffer = baseType + ' ' + id->GetC_Name();
// óäàëÿåì ïðîáåëû
if( outBuffer[outBuffer.length()-1] == ' ' )
outBuffer.erase(outBuffer.end()-1);
if( outBuffer[0] == ' ' )
outBuffer.erase(outBuffer.begin());
}
// ïå÷àòàòü ïðåôèêñíûå ïðîèçâîäíûå òèïû è ñîõðàíÿòü èõ â áóôåð
void CTypePrinter::PrintPointer( string &buf, int &ix, bool &namePrint )
{
bool isPrint = false;
for( ; ix < type.GetDerivedTypeList().GetDerivedTypeCount(); ix++, isPrint++ )
{
const DerivedType &dt = *type.GetDerivedTypeList().GetDerivedType(ix);
DerivedType::DT dtc = dt.GetDerivedTypeCode();
// ññûëêà è óêàçàòåëü îáîçíà÷àþòñÿ îäíèì ñèìâîëîì
if( dtc == DerivedType::DT_REFERENCE || dtc == DerivedType::DT_POINTER )
buf = '*' + buf;
// ìåíÿåì áàçîâûé òèï íà int è âûõîäèì èç öèêëà
else if( dtc == DerivedType::DT_POINTER_TO_MEMBER )
{
// åñëè èìååì óêàçàòåëü íà ÷ëåí-ôóíêöèþ, ïðåîáðàçóåì åãî â óêàçàòåëü
// íà ôóíêöèþ,
if( ix != type.GetDerivedTypeList().GetDerivedTypeCount()-1 &&
type.GetDerivedTypeList().GetDerivedType(ix+1)->GetDerivedTypeCode() ==
DerivedType::DT_FUNCTION_PROTOTYPE )
{
buf = '*' + buf;
INTERNAL_IF( !thisBuf.empty() );
PrintThis( static_cast<const PointerToMember&>(dt).GetMemberClassType(),thisBuf);
}
// èíà÷å ïðåîáðàçóåì òèï â int è âûõîäèì
else
{
baseType = "int";
ix = type.GetDerivedTypeList().GetDerivedTypeCount();
break;
}
}
else
{
// åñëè èìÿ åùå íå áûëî ðàñïå÷àòàíî, ïå÷àòàåì åãî
if( !namePrint )
{
buf = buf + id->GetC_Name();
namePrint = true;
}
if( isPrint )
buf = '(' + buf + ')';
PrintPostfix( buf, ix );
}
}
// åñëè èìÿ òàê è íå áûëî íàïå÷àòàíî, ïå÷àòàåì
if( !namePrint )
{
buf = buf + id->GetC_Name();
namePrint = true;
}
}
// ïå÷àòàòü ïîñòôèêñíûå ïðîèçâîäíûå òèïû è ñîõðàíÿòü â áóôåð
void CTypePrinter::PrintPostfix( string &buf, int &ix )
{
int i;
for( ; ix < type.GetDerivedTypeList().GetDerivedTypeCount(); ix++)
{
const DerivedType &dt = *type.GetDerivedTypeList().GetDerivedType(ix);
DerivedType ::DT dtc = dt.GetDerivedTypeCode();
if( dtc == DerivedType::DT_FUNCTION_PROTOTYPE )
{
const FunctionPrototype &fp = static_cast<const FunctionPrototype &>(dt);
buf += '(';
// åñëè çàäàí this-áóôåð, çíà÷èò ñëåäóåò âûâåñòè ïàðàìåòð this äëÿ
// ìåòîäà è î÷èñòèòü áóôåð
if( !thisBuf.empty() )
{
buf += thisBuf;
thisBuf = "";
if( !fp.GetParametrList().IsEmpty() || fp.IsHaveEllipse() )
buf += ", ";
}
for( i = 0; i<fp.GetParametrList().GetFunctionParametrCount(); i++ )
{
const Parametr &prm = *fp.GetParametrList().GetFunctionParametr(i);
// åñëè ïå÷àòàåì äåêëàðàöèþ (çàäàíî èìÿ), ïðîâåðÿåì, ÷òîáû ó ïàðàìåòðà
// òàêæå áûëî çàäàíî èìÿ
CTypePrinter prmPrinter(prm, id ? &prm : NULL);
prmPrinter.Generate();
// ïðèáàâëÿåì ðàñïå÷àòàííûé ïàðàìåòð
if( prm.IsHaveRegister() )
buf += "register ";
buf += prmPrinter.GetOutBuffer();
if( i < fp.GetParametrList().GetFunctionParametrCount()-1 )
buf += ", ";
}
if( fp.IsHaveEllipse() )
buf += i == 0 ? "..." : ", ...";
buf += ')';
}
else if( dtc == DerivedType::DT_ARRAY )
{
if( dt.GetDerivedTypeSize() > 0 )
buf = buf + '[' + CharString( dt.GetDerivedTypeSize() ).c_str() + ']';
else
buf += "[]";
}
// èíà÷å îïÿòü ñëåäóåò ïå÷àòàòü óêàçàòåëè, òîëüêî ñíà÷àëà
else
{
INTERNAL_IF( dtc != DerivedType::DT_REFERENCE &&
dtc != DerivedType::DT_POINTER &&
dtc != DerivedType::DT_POINTER_TO_MEMBER );
bool nm = true;
PrintPointer(buf, ix, nm);
}
}
}
// çàäàòü èíôîðìàöèþ ãåíåðàöèè äëÿ âèðòóàëüíîãî ìåòîäà
Method::VFData::VFData( int vtIndex, const Method &thisMeth )
: vtIndex(vtIndex),
rootVfCls(static_cast<const ClassType &>(thisMeth.GetSymbolTableEntry()))
{
INTERNAL_IF( !thisMeth.IsVirtual() );
PTypyziedEntity ent = new TypyziedEntity(thisMeth);
INTERNAL_IF( !ent->GetDerivedTypeList().IsFunction() );
const_cast<DerivedTypeList &>(ent->GetDerivedTypeList()).PushHeadDerivedType(
new Pointer(false, false));
CTypePrinter ctp(*ent, thisMeth);
castBuf = '(' + (ctp.Generate(), ctp.GetOutBuffer()) + ')';
}
// ñãåíåðèðîâàòü çàãîëîâîê êëàññà
string ClassGenerator::GenerateHeader( const ClassType &cls )
{
string header;
header = cls.GetBaseTypeCode() == BaseType::BT_UNION ? "union " : "struct ";
header += cls.GetC_Name();
// äîáàâèòü çàãîëîâîê ê âûõîäíîìó áóôåðó
return header;
}
// ñãåíåðèðîâàòü áàçîâûå ïîäîáúåêòû (êëàññû)
void ClassGenerator::GenerateBaseClassList( const BaseClassList &bcl )
{
for( int i = 0; i<bcl.GetBaseClassCount(); i++ )
{
const BaseClassCharacteristic &bcc = *bcl.GetBaseClassCharacteristic(i);
const ClassType &pbcls = bcc.GetPointerToClass();
string subObjBuf = '\t' + GenerateHeader(pbcls);
// åñëè âèðòóàëüíîå íàñëåäîâàíèå, ïðèáàâëÿåì óêàçàòåëü
if( bcc.IsVirtualDerivation() )
subObjBuf += " *";
// ãåíåðèðóåì èìÿ ïîäîáúåêòà
subObjBuf += ' ' + pbcls.GetC_Name() + "so;\n";
clsBuffer += subObjBuf;
}
}
// ñãåíåðèðîâàòü ñïèñîê äàííûõ-÷ëåíîâ è ìåòîäîâ
void ClassGenerator::GenerateMemberList( const ClassMemberList &cml )
{
for( int i = 0; i<cml.GetClassMemberCount(); i++ )
{
const ClassMember &member = *cml.GetClassMember(i);
// åñëè äàííîå-÷ëåí, ãåíåðèðóåì ÷ëåí
if( const DataMember *pobj = dynamic_cast<const DataMember *>(&member) )
{
// typedef-íå ãåíåðèðóåì
if( pobj->GetStorageSpecifier() == ::Object::SS_TYPEDEF )
continue;
// èíà÷å ñãåíåðèðóåì îïðåäåëåíèå
CTypePrinter tp( *pobj, pobj );
tp.Generate();
// åñëè static, ãåíåðèðóåì çà ïðåäåëàìè êëàññà, êàê extern-÷ëåí
if( pobj->GetStorageSpecifier() == ::Object::SS_STATIC )
{
string mbuf = tp.GetOutBuffer();
// åñëè åñòü èíèöèàëèçàòîð, çàäàåì
if( pobj->IsConst() && pobj->GetObjectInitializer() )
mbuf = "const " + mbuf + " = " +
CharString( (int)*pobj->GetObjectInitializer() );
// èíà÷å îáúÿâëÿåì êàê extern
else
mbuf = "extern " + mbuf;
outSideBuffer += mbuf + ";\n";
}
// åñëè áèòîâîå ïîëå
else if( pobj->IsBitField() )
{
const double *v = pobj->GetObjectInitializer();
INTERNAL_IF( !v );
string mbuf = '\t' + tp.GetOutBuffer() + " : " +
CharString( (int)*v ).c_str() + ";\n";
clsBuffer += mbuf;
}
// èíà÷å ãåíåðèðóåì êàê îáû÷íûé ÷ëåí
else
clsBuffer += '\t' + tp.GetOutBuffer() + ";\n";
}
// åñëè ìåòîä, ãåíåðèðóåì åãî çà ïðåäåëàìè êëàññà
else if( const Method *pmeth = dynamic_cast<const Method *>(&member) )
{
// åñëè ìåòîä òðèâèàëüíûé èëè íåäîñòóïíûé èëè àáñòðàêòíûé,
// íå ãåíåðèðóåì åãî
if( pmeth->IsTrivial() || pmeth->IsAbstract() || pmeth->IsUnavaible() )
continue;
CTypePrinter tp( *pmeth, *pmeth,
pmeth->GetStorageSpecifier() != Function::SS_STATIC );
tp.Generate();
const string &mbuf = tp.GetOutBuffer();
if( pmeth->IsInline() )
const_cast<string &>(mbuf) = "inline " + mbuf;
outSideBuffer += tp.GetOutBuffer() + ";\n";
}
}
}
// ðåêóðñèíûé ìåòîä âûçûâàåìûé èç GenerateVTable
void ClassGenerator::GenerateVTable( const ClassType &cls, string *fnArray, int fnArraySize )
{
const VirtualFunctionList &vfl = cls.GetVirtualFunctionList();
for( VirtualFunctionList::const_iterator p = vfl.begin(); p != vfl.end(); p++ )
{
INTERNAL_IF( *p == NULL );
const Method::VFData &vd = (*p)->GetVFData();
INTERNAL_IF( vd.GetVTableIndex() >= fnArraySize );
}
}
// ñãåíåðèðîâàòü òàáëèöó âèðòóàëüíûõ ôóíêöèé äëÿ äàííîãî êëàññà,
// ó÷èòûâàÿ áàçîâûå êëàññû
void ClassGenerator::GenerateVTable( )
{
const int vfcnt = pClass.GetVirtualFunctionCount();
// åñëè âèðòóàëüíûõ ôóíêöèé â êëàññå íåò, ñòðîèòü âèðòóàëüíóþ
// òàáëèöó íå òðåáóåòñÿ
if( vfcnt == 0 )
return;
string *fnBuf = new string[vfcnt];
GenerateVTable( pClass, fnBuf, vfcnt);
// ïîñòóñëîâèå, ÷òîáû âñå ýëåìåíòû áóôåðà áûëè çàïîëíåíû
for( int i = 0; i<vfcnt; i++ )
INTERNAL_IF( fnBuf[i].empty() );
delete [] fnBuf;
}
// ñãåíåðèðîâàòü îïðåäåëåíèå êëàññà è çàâèñèìóþ èíôîðìàöèþ
void ClassGenerator::Generate()
{
// ãåíåðèðóåì çàãîëîâîê
clsBuffer = GenerateHeader(pClass);
// åñëè êëàññ íå ïîëíîñòüþ îáúÿâëåí, ãåíåðèðóåì òîëüêî çàãîëîâîê è âûõîäèì
if( pClass.IsUncomplete() )
{
clsBuffer += ';';
return;
}
// äîáàâëÿåì '{'
clsBuffer += "\n{\n";
int prevBufSize = clsBuffer.size();
// ãåíåðèðóåì áàçîâûå ïîäîáúåêòû
GenerateBaseClassList( pClass.GetBaseClassList() );
// ãåíåðèðóåì ÷ëåíû
GenerateMemberList( pClass.GetMemberList() );
// çäåñü, ïðîâåðÿåì, åñëè áóôåð ñîäåðæèò òîëüêî "\n{\n",
// çíà÷èò â íåãî íè÷åãî íå ñãåíåðèðîâàíî è ñëåäóåò ñãåíåðèðîâàòü
// ïîëå, ÷òîáû êëàññ íå áûë ïóñòûì
if( clsBuffer.size() == prevBufSize )
clsBuffer += "\tint _;";
// çàêðûâàåì ñêîáêó
clsBuffer += "\n};\n\n";
}
// ñãåíåðèðîâàòü, èíèöèàëèçàöèþ êîíñòðóêòîðîì. Âîçâðàùàåò áóôåð ñ âûçîâîì
// êîíñòðóêòîðà. Íå ðàññìàòðèâàåò òðèâèàëüíûå êîíñòðóêòîðû
void DeclarationGenerator::GenerateConstructorCall( const ::Object &obj,
const ConstructorInitializator &ci, string &out )
{
INTERNAL("!!! ðàñïå÷àòàòü âûçîâ êîíñòðóêòîðà è ðåãèñòðàöèþ îáúåêòà");
INTERNAL_IF( !ci.GetConstructor() || ci.GetConstructor()->IsTrivial() );
}
// ñãåíåðèðîâàòü âûðàæåíèå èç èíèöèàëèçàòîðà. Â ñïèñêå âûðàæåíèå äîëæíî áûòü îäíî.
// Åñëè âûðàæåíèå ÿâëÿåòñÿ èíòåðïðåòèðóåìûì è ìîæåò èñïîëüçîâàòüñÿ êàê ïðÿìîé
// èíèöèàëèçàòîð ãëîáàëüíîãî îáúåêòà, âåðíóòü true, èíà÷å false
bool DeclarationGenerator::GenerateExpressionInit( const ::Object &obj,
const ConstructorInitializator &ci, string &out )
{
INTERNAL_IF( ci.GetExpressionList().IsNull() || ci.GetExpressionList()->size() > 1 );
if( ci.GetExpressionList()->empty() )
return true;
// èíà÷å èìååì îäèí èíèöèàëèçàòîð, ðàñïå÷àòàåì åãî
const POperand &exp = ci.GetExpressionList()->front();
INTERNAL_IF( !(exp->IsExpressionOperand() || exp->IsPrimaryOperand()) );
// åñëè èíèöèàëèçàòîð ìîæåò èñïîëüçîâàòüñÿ êàê ïðÿìîé
// äëÿ ãëîáàëüíîãî îáúåêòà óñòàíîâëåí â true
bool directIator = false;
// åñëè èìååì îñíîâíîé îïåðàíä, ïðîàíàëèçèðóåì, ÿâëÿåòñÿ ëè îí èíòåðïðåòèðóåìûì
if( exp->IsPrimaryOperand() )
{
// ïðîâåðêà, ÿâëÿåòñÿ ëè îïåðàíä èíòåðïðåòèðóåìûì
double rval;
if( ExpressionMakerUtils::IsInterpretable(exp, rval) ||
exp->GetType().IsLiteral() )
directIator = true;
}
INTERNAL(" !!!! ðàñïå÷àòàåì âñå âûðàæåíèå â âûõîäíîé áóôåð");
return directIator;
}
// ñãåíåðèðîâàòü èíèöèàëèçàòîð äëÿ îáúåêòà. Åñëè èíèöèàëèçàòîð âîçìîæíî
// ñãåíåðèðîâàòü êàê ïðÿìîé, ãåíåðèðóåì. Èíà÷å ãåíåðèðóåì â áóôåð êîñâåííîé
// èíèöèàëèçàöèè
void DeclarationGenerator::GenerateInitialization( const ::Object &obj )
{
INTERNAL_IF( iator.IsNull() );
// åñëè èíèöèàëèçàòîð êîíñòðóêòîðîì (ëèáî çíà÷åíèåì)
if( iator->IsConstructorInitializator() )
{
const ConstructorInitializator &oci =
static_cast<const ConstructorInitializator &>(*iator);
string out;
// åñëè èíèöèàëèçàöèÿ âûðàæåíèåì
if( !oci.GetConstructor() || oci.GetConstructor()->IsTrivial() )
{
bool directIator = GenerateExpressionInit(obj, oci, out);
if( !out.empty() )
{
// åñëè ñãåíåðèðîâàí ïðÿìîé èíèöèàëèçàòîð èëè èìååì ëîêàëüíûé îáúåêò,
// ãåíåðèðóåì èíèöèàëèçàöèþ ÷åðåç ðàâíî
if( directIator || !global )
outBuffer += " = " + out;
// èíà÷å ãåíåðèðóåì â áóôåð êîñâåííîé èíèöèàëèçàöèè
else
indirectInitBuf = obj.GetC_Name() + " = " + out;
}
}
// èíà÷å, èíèöèàëèçèðóåì êîíñòðóêòîðîì
else
GenerateConstructorCall(obj, oci, out);
}
// èíà÷å èíèöèàëèçàòîð ÿâëÿåòñÿ ñïèñî÷íûì
else
{
INTERNAL("íå ðåàëèçîâàíî");
}
}
// ñãåíåðèðîâàòü äåêëàðàöèþ
void DeclarationGenerator::Generate()
{
// ðàñïå÷àòàåì äåêëàðàöèþ îáúåêòà
if( declarator.IsObject() )
{
const ::Object &obj = static_cast<const ::Object &>(declarator);
CTypePrinter ctp( declarator, &obj );
ctp.Generate();
outBuffer += ctp.GetOutBuffer();
// äîáàâèì ê äåêëàðàöèè ñïåöèôèêàòîð õðàíåíèÿ, åñëè åñòü.
// Äëÿ âûõîäíîãî êîäà èìååò çíà÷åíèå òîëüêî extern, static è register
if( (obj.GetStorageSpecifier() == ::Object::SS_STATIC &&
!obj.GetSymbolTableEntry().IsClassSymbolTable()) ||
obj.GetStorageSpecifier() == ::Object::SS_EXTERN ||
(!global && obj.GetStorageSpecifier() == ::Object::SS_REGISTER) )
outBuffer = ManagerUtils::GetObjectStorageSpecifierName(
obj.GetStorageSpecifier() ) + ' ' + outBuffer;
// åñëè èíèöèàëèçàòîð ïðèñóòñòâóåò, ñãåíåðèðóåì èíèöèàëèçàöèþ äëÿ îáúåêòà
if( !iator.IsNull() )
GenerateInitialization(obj);
}
// ðàñïå÷àòàåì äåêëàðàöèþ ôóíêöèè
else
{
// ó ôóíêöèè íå äîëæíî áûòü èíèöèàëèçàòîðà
INTERNAL_IF( !iator.IsNull() );
const Function &fn = static_cast<const Function &>(declarator);
CTypePrinter ctp( declarator, fn, false );
ctp.Generate();
outBuffer += ctp.GetOutBuffer();
if( fn.GetStorageSpecifier() == Function::SS_STATIC )
outBuffer = "static " + outBuffer;
else if( fn.GetStorageSpecifier() == Function::SS_STATIC )
outBuffer = "extern " + outBuffer;
// äîáàâèì ñïåöèôèêàòîð inline
if( fn.IsInline() )
outBuffer = "inline " + outBuffer;
}
// â êîíöå äîáàâëÿåì ';'
outBuffer += ";\n";
}
// ñîçäàòü íîâûé âðåìåííûé îáúåêò
const TemporaryObject &TemporaryManager::CreateTemporaryObject( const TypyziedEntity &type )
{
// åñëè èìååì íåèñïîëüçóåìûå îáúåêòû, âåðíåì èõ
if( unUsed > 0 )
{
for( TemporaryList::iterator p = temporaryList.begin();
p != temporaryList.end(); p++ )
if( !(*p).IsUsed() )
return (*p).SetUsed(), unUsed--, (*p);
INTERNAL("îøèáêà â ïîäñ÷åòå íåèñïîëüçóåìûõ âðåìåííûõ îáúåêòîâ");
}
// èíà÷å ñîçäàåì âðåìåííûé îáúåêò âðó÷íóþ è ãåíåðèðóåì äåêëàðàöèþ
INTERNAL_IF( !genBuffer.empty() );
TemporaryObject temporary(type);
static LocalSymbolTable lst(GetScopeSystem().GetGlobalSymbolTable());
Identifier id( temporary.GetName().c_str(), &lst );
// ãåíåðèðóåì äåêëàðàöèþ
CTypePrinter ctp( temporary.GetType(), &id );
genBuffer = (ctp.Generate(), ctp.GetOutBuffer());
// âñòàâëÿåì âðåìåííûé îáúåêò â ñïèñîê
temporaryList.push_front(temporary);
return temporaryList.front();
}
// îñâîáîäèòü âðåìåííûé îáúåêò
void TemporaryManager::FreeTemporaryObject( TemporaryObject &tobj )
{
tobj.SetUnUsed();
unUsed++;
// åñëè îáúåêò èìååò êëàññîâûé òèï è íå òðèâèàëüíûé äåñòðóêòîð,
// âûçîâåì ôóíêöèþ óíè÷òîæåíèÿ îáúåêòà
const TypyziedEntity &type = tobj.GetType();
if( type.GetBaseType().IsClassType() && type.GetDerivedTypeList().IsEmpty() &&
static_cast<const ClassType &>(type.GetBaseType()).GetDestructor() &&
!static_cast<const ClassType &>(type.GetBaseType()).GetDestructor()->IsTrivial() )
{
// áóôåð äîëæåí áûòü ïóñòûì ïðè îñâîáîæäåíèè îáúåêòà
INTERNAL_IF( !genBuffer.empty() );
genBuffer = "__destroy_last_registered_object();";
}
}
// ðåêóðñèâíûé ìåòîä ãåíåðàöèè ïóòè
bool ExpressionGenerator::PrintPathToBase(
const ClassType &cur, const ClassType &base, string &out )
{
const BaseClassList &bcl = cur.GetBaseClassList();
for( int i = 0; i<bcl.GetBaseClassCount(); i++ )
{
const BaseClassCharacteristic &bcc = *bcl.GetBaseClassCharacteristic(i);
// åñëè êëàññû ñîâïàëè, ïå÷àòàåì è âûõîäèì
if( &bcc.GetPointerToClass() == &base )
{
out += base.GetC_Name() + "so" + (bcc.IsVirtualDerivation() ? "->" : ".");
return true;
}
// èíà÷å ïðîâåðÿåì, åñëè êëàññ íàõîäèòñÿ âûøå â èåðàðõèè, òàêæå äîáàâëÿåì åãî
else if( PrintPathToBase(bcc.GetPointerToClass(), base, out) )
{
// äîáàâëÿåì ïîäîáúåêò ñïåðåäè
out = bcc.GetPointerToClass().GetC_Name() + "so" +
(bcc.IsVirtualDerivation() ? "->" : ".") + out;
return true;
}
}
return false;
}
// ñãåíåðèðîâàòü ïóòü îò òåêóùåãî êëàññà ê áàçîâîìó. Åñëè êëàññû ñîâïàäàþò,
// íè÷åãî íå ãåíåðèðîâàòü. Åñëè áàçîâûé êëàññ îòñóòñòâóåò â èåðàðõèè - âíóòðåííÿÿ îøèáêà
const string &ExpressionGenerator::PrintPathToBase( const ClassType &cur, const ClassType &base )
{
static string out;
out = "";
// åñëè èçíà÷àëüíî çàäàííûå êëàññû ñîâïàëè, íè÷åãî íå ïå÷àòàåì
if( &cur == &base )
return out;
INTERNAL_IF( !PrintPathToBase(cur, base, out) );
return out;
}
// ðàñïå÷àòàòü îñíîâíîé îïåðàíä. Ôëàã printThis óêàçûâàåò íà àâòîìàòè÷åñêóþ
// ïîäñòàíîâêó óêàçàòåëÿ this äëÿ íåñòàòè÷åñêèõ è íå typedef äàííûõ ÷ëåíîâ.
// Âîçâðàùàåò äåéñòâèòåëüíóþ òèïèçèðîâàííóþ ñóùíîñòü äëÿ äàëüíåéøåãî àíàëèçà
const TypyziedEntity &ExpressionGenerator::PrintPrimaryOperand(
const PrimaryOperand &po, bool printThis, string &out )
{
const TypyziedEntity &entity = po.GetType().IsDynamicTypyziedEntity() ?
static_cast<const DynamicTypyziedEntity &>(po.GetType()).GetOriginal() : po.GetType();
// åñëè îáúåêò
if( entity.IsObject() )
{
const ::Object &obj = static_cast<const ::Object &>(entity);
// â ëþáîì ñëó÷àå ðàñïå÷àòàåì ïîëíûé ïóòü ê ÷ëåíó è åñëè òðåáóåòñÿ
// ðàñïå÷àòàåì this
if( obj.IsClassMember() &&
!static_cast<const DataMember &>(obj).IsStaticMember() )
{
INTERNAL_IF( thisCls == NULL );
out = (printThis ? "this->" : "") + PrintPathToBase(*thisCls,
static_cast<const ClassType &>(obj.GetSymbolTableEntry()) ) + obj.GetC_Name();
}
// èíà÷å ðàñïå÷àòûâàåì ïðîñòî èìÿ
else
out = obj.GetC_Name();
}
// åñëè ôóíêöèÿ, ïðîñòî ïîäñòàâëÿåì èìÿ
else if( entity.IsFunction() )
out = static_cast<const Function &>(entity).GetC_Name();
// åñëè ïàðàìåòð ïîäñòàâëÿåì èìÿ
else if( entity.IsParametr() )
out = static_cast<const Parametr &>(entity).GetC_Name();
// åñëè ëèòåðàë, ïîäñòàâëÿåì áóôåð ñ ëèòåðàëîì
else if( entity.IsLiteral() )
out = static_cast<const Literal &>(entity).GetLiteralValue().c_str();
// åñëè êîíñòàíòà ïåðå÷èñëåíèÿ, ïîäñòàâëÿåì öåëîå çíà÷åíèå
else if( entity.IsEnumConstant() )
out = CharString(static_cast<const EnumConstant &>(entity).GetConstantValue()).c_str();
// â ïðîòèâíîì ñëó÷àå îñòàåòñÿ òîëüêî this. Ïðîâåðèì, ÷òîáû this-êëàññ
// ïðèñóòñòâîâë è òèïû ñîâïàäàëè
else
{
INTERNAL_IF( thisCls == NULL || &entity.GetBaseType() != thisCls ||
!entity.GetDerivedTypeList().IsPointer() ||
entity.GetDerivedTypeList().GetDerivedTypeCount() != 1 );
out = "this";
}
return entity;
}
// ðàñïå÷àòàòü óíàðíîå âûðàæåíèå
void ExpressionGenerator::PrintUnary( const UnaryExpression &ue, string &out )
{
int op = ue.GetOperatorCode();
const POperand &opr = ue.GetOperand();
switch( op )
{
case '!':
case '~':
case '+':
case '-':
case '*':
out = (char)op + PrintExpression(opr);
break;
case INCREMENT:
out = PrintExpression(opr) + "++";
break;
case DECREMENT:
out = PrintExpression(opr) + "--";
break;
case -INCREMENT:
out = "++" + PrintExpression(opr);
break;
case -DECREMENT:
out = "--" + PrintExpression(opr);
break;
case GOC_REFERENCE_CONVERSION:
// ïðîïóñêàåì ðàçèìåíîâàíèå, ò.ê. ãåíåðàòîð ñäåëàåò ýòî àâòîìàòè÷åñêè
out = PrintExpression(opr);
break;
case '&':
// åñëè èìååì âçÿòèå óêàçàòåëÿ íà ÷ëåí, ãåíåðèðóåì offsetof,
if( opr->IsPrimaryOperand() &&
ue.GetType().GetDerivedTypeList().IsPointerToMember() )
{
const DataMember *dm = dynamic_cast<const DataMember *>(&opr->GetType());
INTERNAL_IF( dm == NULL );
out = "offsetof(" + TranslatorUtils::GenerateClassHeader(
static_cast<const ClassType &>(dm->GetSymbolTableEntry()) ) + ", ";
string dmBuf;
PrintPrimaryOperand( static_cast<const PrimaryOperand&>(*opr), false, dmBuf);
out += dmBuf + ')';
}
// èíà÷å îñòàâëÿåì áåç èçìåíåíèé
else
out = "&" + PrintExpression(opr);
break;
case KWTYPEID:
case KWTHROW:
default:
INTERNAL( "'ExpressionGenerator::PrintUnary': íåèçâåñòíûé óíàðíûé îïåðàòîð");
}
}
// ðàñïå÷àòàòü óíàðíîå âûðàæåíèå
void ExpressionGenerator::PrintBinary( const BinaryExpression &be, string &out )
{
int op = be.GetOperatorCode();
switch( op )
{
case '.':
case ARROW:
{
INTERNAL_IF( !be.GetOperand2()->IsPrimaryOperand() );
out = PrintExpression(be.GetOperand1()) + (op == '.' ? "." : "->");
string idBuf;
PrintPrimaryOperand( static_cast<const PrimaryOperand &>(*be.GetOperand2()),
false, idBuf);
out += idBuf;
break;
}
case OC_CAST:
case GOC_BASE_TO_DERIVED_CONVERSION:
case GOC_DERIVED_TO_BASE_CONVERSION:
case KWREINTERPRET_CAST:
case KWSTATIC_CAST:
case KWCONST_CAST:
case KWDYNAMIC_CAST:
case ARROW_POINT:
case DOT_POINT:
INTERNAL("!! íå ðåàëèçîâàíî");
case OC_ARRAY:
out = '(' + PrintExpression(be.GetOperand1()) + ")[" +
PrintExpression(be.GetOperand2() ) + ']';
break;
default:
{
string opbuf = ExpressionPrinter::GetOperatorName(op);
out = PrintExpression(be.GetOperand1() ) + ' ' +
opbuf + ' ' + PrintExpression(be.GetOperand2());
}
break;
}
}
// ðàñïå÷àòàòü óíàðíîå âûðàæåíèå
void ExpressionGenerator::PrintTernary( const TernaryExpression &te, string &out )
{
INTERNAL_IF( te.GetOperatorCode() != '?' );
out = PrintExpression(te.GetOperand1()) + " ? " +
PrintExpression(te.GetOperand2()) + " : " + PrintExpression(te.GetOperand3());
}
// ðàñïå÷àòàòü óíàðíîå âûðàæåíèå
void ExpressionGenerator::PrintFunctionCall( const FunctionCallExpression &fce, string &out )
{
const POperand &fn = fce.GetFunctionOperand();
string objBuf;
// åñëè âûðàæåíèå - îáðàùåíèå ê ÷ëåíó, ïîìåñòèòü îáúåêò ïåðâûì ïàðàìåòðîì
if( fn->IsExpressionOperand() )
{
int op = static_cast<const Expression &>(*fn).GetOperatorCode();
if( op == '.' || op == ARROW || op == DOT_POINT || op == ARROW_POINT )
objBuf = PrintExpression(static_cast<const BinaryExpression &>(*fn).GetOperand1());
}
}
// ðàñïå÷àòàòü óíàðíîå âûðàæåíèå
void ExpressionGenerator::PrintNewExpression( const NewExpression &ne, string &out )
{
}
// êîîðäèíàòîð ðàñïå÷àòêè âûðàæåíèé, âûçûâàåò ìåòîä ñîîòâåòñòâóþùèé îïåðàòîðó.
// prvOp - êîä ïðåäûäóùåãî îïåðàòîðà, åñëè îïåðàòîðà íå áûëî -1
string ExpressionGenerator::PrintExpression( const POperand &opr )
{
INTERNAL_IF( opr.IsNull() || !(opr->IsExpressionOperand() || opr->IsPrimaryOperand()) );
string out;
// åñëè áûë îïåðàòîð îáðàùåíèÿ ê ÷ëåíó èëè âçÿòèÿ àäðåñà íà ÷ëåí,
// ýòîò ôðàãìåíò âûïîëíÿåòñÿ ïðè ðàñïå÷àòêå ýòèõ îïåðàòîðîâ
if( opr->IsPrimaryOperand() )
PrintPrimaryOperand( static_cast<const PrimaryOperand &>(*opr), true, out );
// èíà÷å îðèåíòèðóåìñÿ íà òèï âûðàæåíèÿ
else
{
const Expression &exp = static_cast<const Expression &>(*opr);
if( exp.IsUnary() )
PrintUnary( static_cast<const UnaryExpression &>(exp), out );
else if( exp.IsBinary() )
PrintBinary( static_cast<const BinaryExpression &>(exp), out );
else if( exp.IsTernary() )
PrintTernary( static_cast<const TernaryExpression &>(exp), out );
else if( exp.IsFunctionCall() )
PrintFunctionCall( static_cast<const FunctionCallExpression&>(exp), out );
else if( exp.IsNewExpression() )
PrintNewExpression( static_cast<const NewExpression &>(exp), out );
else
INTERNAL( "íåèçâåñòíûé òèï âûðàæåíèÿ" );
// åñëè âûðàæåíèå â ñêîáêàõ, ïîìåñòèòü åãî
if( exp.IsInCramps() )
out = '(' + out + ')';
}
// åñëè áûëà ññûëêà, ðàçèìåíîâûâàåì
if( opr->GetType().GetDerivedTypeList().IsReference() )
out = "(*" + out + ')';
return out;
}
// ñãåíåðèðîâàòü âûðàæåíèå
void ExpressionGenerator::Generate()
{
// åñëè âûðàæåíèå ÿâëÿåòñÿ îñíîâíûì îïåðàíäîì, ñðàçó ãåíåðèðóåì
if( exp->IsPrimaryOperand() )
PrintPrimaryOperand( static_cast<const PrimaryOperand &>(*exp), true, outBuffer );
else
outBuffer = PrintExpression(exp);
}