.NAME Type of loop counter

.DESCRIPTION
	A for loop shall contain a single loop-counter which 
shall not have floating type. 

.COMMENT V7.0

.SEVERITY Required

.COMMENT
Please refer to the MISRA C++:2008 document for further details (www.misra-cpp.com)
KNOWN LIMITATIONS:
- Loop-counters modified within the for body are not accounted for when evaluating this rule

.COMMAND tcl

.REQUIRED cpp_semantic

.CODE

::logiscope::include -once common utilities.tcl

proc compute {standardName tree} {
  # Check all ... nodes
  utilities::filterTree $tree [list [namespace current]::check]
}

# TODO
# Chercher tous les identifier du test ==> listId
# Parser l'incr�ment. D�s qu'un identifier de listId est � gauche d'un = += -= ou dans un ++ --, incr�menter le compteur de compteurs
# A partir du deuxi�me compteur trouv�, violation
#Ajouter en restriction qu'on ne va pas d�tecter les modifications de compteurs dans le corps
proc check { node } {
	set hasTest 0
	set testIdList ""
	set hasMod 0
	variable testIdentifiers
	variable counterUsage
	
	# Look for "for" loop 
	if { [::utilities::isTreeOperator $node for] } {
		# Extract test and modifier statements of the "for"
		# Look for all identifiers in the test
		if {[expr [::logiscope::treeLength $node] > 1]} {
			set hasTest 1
			set forTest [::logiscope::treeGetSon $node EXPR_OPT_2]
			set testIdentifiers ""
			extractIdentifiers $forTest
		}
		
		if {[expr [::logiscope::treeLength $node] > 2]} {
			set hasMod 1
			set forMod [::logiscope::treeGetSon $node EXPR_OPT_3]
			# Check if the identifiers are used in the modifier part
			set counterUsage 0
			checkMod $forMod
		}
	}
	return 1
}

proc extractIdentifiers {node} {
	variable testIdentifiers
	if { [::utilities::isTreeOperator $node identifier] } {
		if {![::utilities::isTreeOperator [::logiscope::treeUp $node] call]} {
			lappend testIdentifiers [::utilities::getName $node]
		}
	}
	
	::logiscope::forobj child $node treeChild {
		extractIdentifiers $child
	}	
}

proc checkMod {node} {
	variable testIdentifiers
	variable counterUsage
	set curName [::utilities::getName $node]
	# The identifier can't be part of a [=,+=,-=, ++,--]
	set badOpe [list ass plus_ass minus_ass]
	set badIncr [list post_incr post_decr pre_incr pre_decr]

	if {[expr [lsearch $badOpe $curName]!= -1]} {
		# Only the left part of operator is tested
		set curElt [::logiscope::treeDown $node 0]
		checkIdentifier $curElt
	}

	if {[expr [lsearch $badIncr $curName]!= -1]} {
		# Check the increment attribute
		set curElt [::logiscope::treeDown $node 0]
		checkIdentifier $curElt
	}

	::logiscope::forobj child $node treeChild {
		checkMod $child
	}		
}

proc checkIdentifier {node} {
	variable testIdentifiers
	variable counterUsage	
	if { [::utilities::isTreeOperator $node identifier] } {
		set foundIdx [lsearch $testIdentifiers [::utilities::getName $node]]
		if {[expr $foundIdx!= -1]} {
			incr counterUsage
			set testIdentifiers [lreplace $testIdentifiers $foundIdx $foundIdx]
			if {[expr $counterUsage == 1]} {
				set curScope [::Semantic::getScopeOfNode $node]
				set curType [::Semantic::getTypeOf $node]
				set curTypeName "N/A"
				if {[expr $curType != -1]} {
					set curTypeName [::Semantic::getAttribute $curType name]
					if {[expr [lsearch [list double float "long double"] $curTypeName]!= -1]} {
						::logiscope::addViolation $node
					}
				}
			}
			if {[expr $counterUsage >1]} {
				::logiscope::addViolation $node
			}
		}
	}
}
