from pycparser import parse_file, c_ast
import utilities

class FunctionDefinitionRecorder(c_ast.NodeVisitor):
	def __init__(self):
		self.defined_functions = []
		self.def_locations = []

	def visit_FuncDef(self, node):
		self.defined_functions.append(node.decl.name)
		self.def_locations.append(node.decl.coord)

class ParsedCFile:
	"""
	An object allowing one to explore the AST of a C file.  The file is 
	parsed using pycparser and various convenience routines are given to
	speed access to certain parts of the file.  
	"""

	def __init__(self, filepath, arch):
		self.filepath = filepath
		self.arch = arch

		self._parse_file()

	def _parse_file(self):
		"""
		Preprocess and parse C file into an AST
		"""

		#We need to set the CPU type to pull in the right register definitions
		#only preprocess the file (-E) and get rid of gcc extensions that aren't
		#supported in ISO C.
		args = utilities.build_includes(self.arch.includes())
		args.append('-mcpu=%s' % self.arch.property('chip'))
		args.append('-E')
		args.append('-D__attribute__(x)=')
		args.append('-D__extension__=')
		self.ast = parse_file(self.filepath, use_cpp=True, cpp_path='xc16-gcc', cpp_args=args)

	def defined_functions(self, criterion=lambda x: True):
		visitor = FunctionDefinitionRecorder()
		visitor.visit(self.ast)

		return filter(criterion, visitor.defined_functions)