1
/***************************************************************************
2
begin : Sat Jul 21 2001
3
copyright : (C) 2001 by Victor R�er
4
email : victor_roeder@gmx.de
5
copyright : (C) 2002,2003 by Roberto Raggi
6
email : roberto@kdevelop.org
7
copyright : (C) 2005 by Adam Treat
8
email : manyoso@yahoo.com
9
copyright : (C) 2006 by David Nolden
10
email : david.nolden.kdevelop@art-master.de
11
***************************************************************************/
13
/***************************************************************************
15
* This program is free software; you can redistribute it and/or modify *
16
* it under the terms of the GNU General Public License as published by *
17
* the Free Software Foundation; either version 2 of the License, or *
18
* (at your option) any later version. *
20
***************************************************************************/
22
#include "cppevaluation.h"
23
#include "simplecontext.h"
24
#include "safetycounter.h"
26
extern SafetyCounter safetyCounter;
28
namespace CppEvaluation {
30
void statusLog( const QString& str ) {
31
ifVerboseMajor( dbgMajor() << str << endl );
32
statusBarText( str, 2000 );
34
OperatorSet AllOperators;
36
///These lines register the operators to the list of all operators
37
RegisterOperator< DotOperator > DotReg( AllOperators );
38
RegisterOperator< NestedTypeOperator > NestedReg( AllOperators );
39
RegisterOperator< ArrowOperator > ArrowReg( AllOperators );
40
RegisterOperator< StarOperator > StarReg( AllOperators );
41
RegisterOperator< AddressOperator > AddressReg( AllOperators );
42
RegisterOperator< IndexOperator > IndexReg( AllOperators );
43
RegisterOperator< ParenOperator > ParenReg( AllOperators );
45
template<class To, class From>
46
QValueList<To> convertList( const QValueList<From>& from ) {
48
for( typename QValueList<From>::const_iterator it = from.begin(); it != from.end(); ++it ) {
54
QString nameFromType( SimpleType t ) {
55
return t->fullTypeResolved();
58
QString Operator::printTypeList( QValueList<EvaluationResult>& lst )
61
for( QValueList<EvaluationResult>::iterator it = lst.begin(); it != lst.end(); ++it ) {
62
ret += "\"" + (*it)->fullNameChain() + "\", ";
64
ret.truncate( ret.length() - 3 );
68
void Operator::log( const QString& msg ) {
69
statusLog( "\"" + name() + "\": " + msg );
70
//ifVerboseMajor( dbgMajor() << "\"" << name() << "\": " << msg << endl );
73
OperatorSet::~OperatorSet() {
74
for( QValueList< Operator* >::iterator it = m_operators.begin(); it != m_operators.end(); ++it ) {
79
OperatorIdentification OperatorSet::identifyOperator( const QString& str_ , Operator::BindingSide allowedBindings) {
80
QString str = str_.stripWhiteSpace();
81
for( OperatorList::iterator it = m_operators.begin(); it != m_operators.end(); ++it ) {
82
if( ((*it)->binding() & allowedBindings) == (*it)->binding() ) {
83
if( OperatorIdentification ident = (*it)->identify( str ) ) {
89
return OperatorIdentification();
92
OperatorIdentification UnaryOperator::identify( QString& str ) {
93
OperatorIdentification ret;
94
if( str.startsWith( m_identString ) ) {
96
ret.end = m_identString.length();
103
EvaluationResult UnaryOperator::apply( QValueList<EvaluationResult> params, QValueList<EvaluationResult> innerParams ) {
104
if( !checkParams( params ) ) {
105
log( QString("parameter-check failed: %1 params: ").arg( params.size() ) + printTypeList( params ) );
106
return EvaluationResult();
108
EvaluationResult t = unaryApply( params.front(), innerParams );
111
log( "could not apply \"" + name() + "\" to \"" + nameFromType( params.front() ) + "\"");
113
log( "operator \"" + name() + "\" applied on \"" + nameFromType( params.front() ) + "\": returning unresolved type \"" + nameFromType( t ) + "\"");
119
EvaluationResult NestedTypeOperator::unaryApply( EvaluationResult param, const QValueList<EvaluationResult>& /*innerParams*/ ) {
123
EvaluationResult DotOperator::unaryApply( EvaluationResult param, const QValueList<EvaluationResult>& /*innerParams*/ ) {
124
if( param->totalPointerDepth() == 0 ) {
127
log( "failed to apply dot-operator to " + param->fullNameChain() + " because the pointer-depth is wrong" );
128
return EvaluationResult();
133
EvaluationResult ArrowOperator::unaryApply( EvaluationResult param, const QValueList<EvaluationResult>& innerParams ) {
134
if( param->totalPointerDepth() == 1 ) {
135
param->setTotalPointerDepth( param->totalPointerDepth() - 1 );
138
if( param->resolved() ) {
139
if( param->totalPointerDepth() == 0 ) {
140
return param->resolved()->applyOperator( SimpleTypeImpl::ArrowOp , convertList<LocateResult, EvaluationResult>(innerParams) );
142
log("failed to apply arrow-operator to " + param->fullNameChain() + " because the pointer-depth is wrong" );
143
return EvaluationResult();
146
log( "failed to apply arrow-operator to unresolved type" );
147
return EvaluationResult();
152
EvaluationResult StarOperator::unaryApply( EvaluationResult param, const QValueList<EvaluationResult>& /*innerParams*/ ) {
153
if( param->totalPointerDepth() > 0 ) {
154
param->setTotalPointerDepth( param->totalPointerDepth() - 1 );
157
if( param->resolved() ) {
158
return param->resolved()->applyOperator( SimpleTypeImpl::StarOp );
160
log( "failed to apply star-operator to unresolved type" );
161
return EvaluationResult();
166
EvaluationResult AddressOperator::unaryApply( EvaluationResult param, const QValueList<EvaluationResult>& /*innerParams*/ ) {
167
param->setTotalPointerDepth( param->totalPointerDepth() + 1 );
171
OperatorIdentification UnaryParenOperator::identify( QString& str ) {
172
OperatorIdentification ret;
173
if( str.startsWith( QString( identString()[0] ) ) ) {
175
ret.end = findClose( str, 0 );
176
if( ret.end == -1 ) {
180
if( str[ret.end] == identString()[1] ) {
185
///Try to extract the parameter-strings.
186
ParamIterator it( identString(), str.mid( ret.start, ret.end - ret.start ) );
189
ret.innerParams << (*it).stripWhiteSpace();
203
EvaluationResult IndexOperator::unaryApply( EvaluationResult param, const QValueList<EvaluationResult>& innerParams ) {
204
if( param->totalPointerDepth() > 0 ) {
205
param->setTotalPointerDepth( param->totalPointerDepth() - 1 );
208
if( param->resolved() ) {
209
return param->resolved()->applyOperator( SimpleTypeImpl::IndexOp, convertList<LocateResult>( innerParams ) );
211
log( "failed to apply index-operator to unresolved type" );
212
return EvaluationResult();
217
EvaluationResult ParenOperator::unaryApply( EvaluationResult param, const QValueList<EvaluationResult>& innerParams ) {
219
if( param->resolved() ) {
220
return param->resolved()->applyOperator( SimpleTypeImpl::ParenOp, convertList<LocateResult>(innerParams) );
222
log( "failed to apply paren-operator to unresolved type" );
223
return EvaluationResult();
227
return innerParams[0];
231
ExpressionEvaluation::ExpressionEvaluation( CppCodeCompletion* data, ExpressionInfo expr, OperatorSet& operators, const HashedStringSet& includeFiles, SimpleContext* ctx ) : m_data( data ), m_ctx( ctx ), m_expr( expr ), m_global(false), m_operators( operators ), m_includeFiles( includeFiles ) {
232
safetyCounter.init();
234
ifVerboseMajor( dbgMajor( ) << "Initializing evaluation of expression " << expr << endl );
236
if ( expr.expr().startsWith( "::" ) )
238
expr.setExpr( expr.expr().mid( 2 ) );
242
//m_expr = m_data->splitExpression( expr.expr() ).join("");
245
EvaluationResult ExpressionEvaluation::evaluate() {
246
EvaluationResult res;
247
res = evaluateExpressionInternal( m_expr.expr(), m_ctx->global(), m_ctx, m_ctx, /*m_expr.canBeTypeExpression() cannot be safely determined*/true );
249
ExpressionInfo ex = res.expr; ///backup and set the type which was chosen while the evaluation-process
256
EvaluationResult ExpressionEvaluation::evaluateExpressionInternal( QString expr, EvaluationResult scope, SimpleContext * ctx, SimpleContext* innerCtx , bool canBeTypeExpression) {
257
LogDebug d( "#evl#" );
258
if( expr.isEmpty() || !safetyCounter ) {
259
scope.expr.t = ExpressionInfo::NormalExpression;
263
/*if( !scope->resolved() ) {
264
ifVerboseMajor( dbgMajor() << "evaluateExpressionInternal(\"" << expr << "\") scope: \"" << scope->fullTypeStructure() << "\" is unresolved " << endl );
265
return EvaluationResult();
268
ifVerboseMajor( dbgMajor() << "evaluateExpressionInternal(\"" << expr << "\") scope: \"" << scope->fullNameChain() << "\" context: " << ctx << endl );
270
expr = expr.stripWhiteSpace();
272
///Find the rightmost operator with the lowest priority, for the first split.
273
QValueList<OperatorIdentification> idents;
274
for( uint a = 0; a < expr.length(); ++a ) {
275
QString part = expr.mid( a );
276
OperatorIdentification ident = m_operators.identifyOperator( part );
278
ifVerboseMajor( dbgMajor() << "identified \"" << ident.op->name() << "\" in string " << part << endl );
284
if( isLeftParen( part[0] ) ) {
285
int jump = findClose( part, 0 );
292
if( !idents.isEmpty() ) {
293
OperatorIdentification lowest;
295
for( QValueList<OperatorIdentification>::iterator it = idents.begin(); it != idents.end(); ++it ) {
297
if( lowest.op->priority() >= (*it).op->priority() )
305
QString leftSide = expr.left( lowest.start ).stripWhiteSpace();
306
QString rightSide = expr.right( expr.length() - lowest.end ).stripWhiteSpace();
308
EvaluationResult left, right;
309
if( !leftSide.isEmpty() ) {
310
left = evaluateExpressionInternal( leftSide, scope, ctx, innerCtx, lowest.op->canBeType( Operator::Left ) );
315
if( !left && (lowest.op->binding() & Operator::Left) ) {
316
ifVerboseMajor( dbgMajor() << "problem while evaluating expression \"" << expr << "\", the operator \"" << lowest.op->name() << "\" has a binding to the left side, but no left side could be evaluated: \"" << leftSide << "\"" << endl );
319
if( !rightSide.isEmpty() && (lowest.op->binding() & Operator::Right) )
320
right = evaluateExpressionInternal( rightSide, SimpleType(), ctx, innerCtx, lowest.op->canBeType( Operator::Right ) );
322
if( !right && (lowest.op->binding() & Operator::Right) ) {
323
ifVerboseMajor( dbgMajor() << "problem while evaluating expression \"" << expr << "\", the operator \"" << lowest.op->name() << "\" has a binding to the right side, but no right side could be evaluated: \"" << rightSide << "\"" << endl );
326
QValueList<EvaluationResult> innerParams;
327
QValueList<EvaluationResult> params;
328
if( lowest.op->binding() & Operator::Left ) params << left;
329
if( lowest.op->binding() & Operator::Right ) params << right;
331
for( QValueList<QString>::iterator it = lowest.innerParams.begin(); it != lowest.innerParams.end(); ++it ) {
332
ifVerboseMajor(dbgMajor() << "evaluating inner parameter \"" + *it + "\"" );
333
innerParams << evaluateExpressionInternal( (*it), SimpleType(), innerCtx, innerCtx, lowest.op->canBeType( Operator::Neutral ) );
336
EvaluationResult applied = lowest.op->apply( params, innerParams );
338
statusLog( "\"" + expr + "\": failed to apply the operator \"" + lowest.op->name() + "\"" );
341
if( ! (lowest.op->binding() & Operator::Left) && !leftSide.isEmpty() ) {
342
///When the operator has no binding to the left, the left side should be empty.
343
statusLog( "\"" + expr + "\": problem with the operator \"" + lowest.op->name() + ", it has no binding to the left side, but the left side is \""+ leftSide + "\"" );
346
if( ! (lowest.op->binding() & Operator::Right) && !rightSide.isEmpty() ) {
347
///When the operator has no binding to the right, we should continue evaluating the right side, using the left type as scope.
349
return evaluateExpressionInternal( rightSide, applied, 0, innerCtx, lowest.op->canBeType( Operator::Right ) );
354
ifVerboseMajor( dbgMajor() << " could not find an operator in " << expr << endl );
355
return evaluateAtomicExpression( expr, scope, ctx );
359
//dbgMajor() << " could not evaluate " << expr << endl;
360
ifVerboseMajor( dbgMajor() << "evaluating \"" << expr << "\" as atomic expression" << endl );
362
TypeDesc exp = m_ctx->container()->resolveTemplateParams( TypeDesc(expr) );
364
ifVerboseMajor( dbgMajor() << "after template-parameter resolution: \"" << exp.fullNameChain() << "\"" << endl );
366
EvaluationResult res = evaluateAtomicExpression( exp, scope, ctx, canBeTypeExpression );
370
/**This function needs a clean workover.
371
* An atomic expression is one that only consists of a type-, function- or variable-name(may include '::')
373
EvaluationResult ExpressionEvaluation::evaluateAtomicExpression( TypeDesc expr, EvaluationResult scope, SimpleContext * ctx, bool canBeTypeExpression ) {
374
LogDebug d( "#evt#");
375
if( !safetyCounter || !d ) return SimpleType();
376
bool canBeItemExpression = true; ///To be implemented
379
expr.setIncludeFiles( scope.resultType->includeFiles() );
381
expr.setIncludeFiles( m_includeFiles );
385
ifVerboseMajor( dbgMajor() << "evaluateAtomicExpression(\"" << expr.name() << "\") scope: \"" << scope->fullNameChain() << "\" context: " << ctx << endl );
387
EvaluationResult bestRet;
390
if( expr.name().isEmpty() )
393
TypePointer searchIn = scope->resolved();
395
statusLog( "scope-type is not resolved" );
396
return EvaluationResult();
400
searchIn = ctx->container().get();
402
if( ctx && canBeItemExpression ) {
403
///Search for variables and functions, first in the current context, and then through the container-classes upwards.
404
// find the variable in the current context
405
SimpleVariable var = ctx->findVariable( expr.name() );
408
TypeDesc d( var.type );
409
d.setIncludeFiles( m_includeFiles );
410
EvaluationResult ret = EvaluationResult( ctx->container()->locateDecType( d ), var.toDeclarationInfo( "current_file" ));
411
ret.expr.t = ExpressionInfo::NormalExpression;
415
SimpleType current = ctx->container();
417
SimpleTypeImpl::TypeOfResult type;
419
SafetyCounter s( 20 );
425
if( !current ) ready = true;
427
type = current->typeOf( expr );
429
bestRet = EvaluationResult( type.type, type.decl );
431
bestRet.expr = expr.fullNameChain();
432
bestRet.expr.t = ExpressionInfo::NormalExpression;
436
if( !ready ) current = current->parent();
440
if( scope.expr.t & ExpressionInfo::TypeExpression )
441
canBeTypeExpression = true;*/
443
if( canBeItemExpression && (!bestRet || bestDepth > 0 ) ) {
445
SimpleTypeImpl::TypeOfResult res = searchIn->typeOf( expr );
448
bestRet = EvaluationResult( res.type, res.decl );
452
if( canBeTypeExpression ) {
454
LocateResult type = searchIn->locateDecType( expr );
457
/** Did we find a constructor within a class? */
458
(type->resolved() && ( bestRet->resolved() && type->resolved()->desc() == bestRet->resolved()->parent()->desc() && bestRet->resolved()->asFunction() ) ) ) {
459
/*if ( type && type->resolved() )
461
EvaluationResult ret = type;
462
ret.expr = expr.fullNameChain();
463
ret.expr.t = ExpressionInfo::TypeExpression;
467
bestRet = EvaluationResult( type );
468
QStringList s = split+exprList;
471
bestRet->append( new TypeDescShared( s.join("::") ) );
478
ifVerboseMajor( dbgMajor() << "evaluateAtomicExpression: \"" << scope.resultType->fullNameChain() << "\"could not locate " << expr.fullNameChain() << endl );
483
// kate: indent-mode csands; tab-width 2;