.NAME A single return per function.

.DESCRIPTION

Only one return instruction is allowed in a function.
This is a basic rule for structured programming.

.SEVERITY Advisory

.COMMAND tcl

.CODE

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

proc compute {standardName tree} {
	
	# Check all subprogram bodies
	utilities::filterTree $tree [list [namespace current]::checkSubprograms]
}


#--------------------------------------------------------------------------
# Checking if current node is a subprogram body and, if yes, compute number of
# return, except last one 
#--------------------------------------------------------------------------
proc checkSubprograms { tree} {
	global nbReturn
	if { [::utilities::isTreeOperator $tree method_decl] } {
		set compound [::logiscope::treeGetSon $tree METHOD_BODY]
		# nothing to do if it is only a declaration
		if { ![::utilities::isTreeOperator $compound compound] } {
			return 0
		}
		# locate statements of subprogram
		set statements [::logiscope::treeGetSon $compound STMTS]
		# if last statemen is return, it is not taken into account in the number of return
		set idx [::logiscope::treeLength $statements]
		set nbReturn 0
		if { "$idx" > 0 && [::utilities::isTreeOperator [::logiscope::treeDown $statements [expr $idx - 1]] return] } {
			set nbReturn -1
		}
		# and now, computing number of return in subprogram
		utilities::filterTree $statements [list [namespace current]::checkStatements]
		# if more than 0 return, it is an error
		if { "$nbReturn" > 0 } {
			::logiscope::addViolation $tree
		}
	}
	return 1
}

#
# checking statements
# +1 for nbReturn if return_statement is found
# end of check if subprogram_body is found
proc checkStatements { tree } {
	global nbReturn
	switch [::utilities::treeOperatorName $tree] {
		methode_decl {
			return 0
		}
		return {
			incr nbReturn 
			return 0
		}
	}
	return 1
}

