function(map_graphsearch)
	set(options)
  	set(oneValueArgs SUCCESSORS VISIT PUSH POP)
  	set(multiValueArgs)
  	set(prefix)
  	cmake_parse_arguments("${prefix}" "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
  	#_UNPARSED_ARGUMENTS
  	# setup functions

  	if(NOT _SUCCESSORS)		
		function(gs_successors result node)
			#ref_isvalid(${node})
			#ans(isref)
			map_isvalid( ${node} )
			ans(ismap)
			list_isvalid(${node}  )
			ans(islist)
			set(res)
			if(ismap)
				map_keys(${node} )
				ans(keys)
				map_values(${node}  ${keys})
				ans(res)
			elseif(islist)
				list_values(${node} )
				ans(values)
			endif()
			set(${result} "${res}" PARENT_SCOPE)
		endfunction()
	else()
		function_import("${_SUCCESSORS}" as gs_successors REDEFINE)
	endif()
	
	if(NOT _VISIT)
		function(gs_visit cancel value)
		endfunction()
	else()
		function_import("${_VISIT}" as gs_visit REDEFINE)
	endif()

	if(NOT _POP)
		function(gs_pop result)
			set(node)
			stack_peek(__gs)
			ans(node)
			if(NOT node)
				set(${result} PARENT_SCOPE)
				return()
			endif()
			stack_pop(__gs )
			ans(node)
			set(${result} "${node}" PARENT_SCOPE)
		endfunction()
	else()
		function_import("${_POP}" as gs_pop REDEFINE)
	endif()

	if(NOT _PUSH)
		function(gs_push node)
			stack_push(__gs ${node})
		endfunction()
	else()
		function_import("${_PUSH}" as gs_push REDEFINE)
	endif()

	# start of algorithm

	# add initial nodes to container
	foreach(node ${_UNPARSED_ARGUMENTS})
		gs_push(${node})
	endforeach()

	# iterate as long as there are nodes to visit
	while(true)
		set(current)
		# get first node
		gs_pop(current)
		if(NOT current)
			break()
		endif()

		set(cancel false)
		# visit node 
		# if cancel is set to true do not add successors
		gs_visit(cancel ${current})
		if(NOT cancel)
			gs_successors(successors ${current})
			foreach(successor ${successors})
				gs_push(${successor})
			endforeach()
		endif()
	endwhile()
endfunction()