/*
 * Copyright 2016, 2017 Tobias Grosser. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    1. Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *
 *    2. Redistributions in binary form must reproduce the above
 *       copyright notice, this list of conditions and the following
 *       disclaimer in the documentation and/or other materials provided
 *       with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY TOBIAS GROSSER ''AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL TOBIAS GROSSER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * The views and conclusions contained in the software and documentation
 * are those of the authors and should not be interpreted as
 * representing official policies, either expressed or implied, of
 * Tobias Grosser.
 */

#include <iostream>
#include <string>
#include <vector>

#include "cpp.h"
#include "isl_config.h"

/* Determine the isl types from which the given class can be implicitly
 * constructed using a unary constructor.
 *
 * Look through all constructors for implicit conversion constructors that take
 * an isl type and add those types, along with the corresponding
 * constructor argument.
 */
void cpp_generator::set_class_construction_types(isl_class &clazz)
{
	for (const auto &cons : clazz.constructors) {
		ParmVarDecl *param;
		QualType type;
		std::string arg_type;

		if (!is_implicit_conversion(Method(clazz, cons)))
			continue;

		param = cons->getParamDecl(0);
		type = param->getOriginalType();
		arg_type = extract_type(type);
		clazz.construction_types.emplace(arg_type, param);
	}
}

/* Determine the isl types from which any (proper) class can be constructed
 * using a unary constructor.
 */
void cpp_generator::set_construction_types()
{
	for (auto &kvp : classes) {
		auto &clazz = kvp.second;
		set_class_construction_types(clazz);
	}
}

/* Construct a generator for C++ bindings.
 *
 * The classes and methods are extracted by the constructor
 * of the generator superclass.
 *
 * Additionally extract information about types
 * that can be converted to a class and copy all methods
 * from superclasses that can be converted to a given class
 * to that class.
 */
cpp_generator::cpp_generator(SourceManager &SM,
	set<RecordDecl *> &exported_types,
	set<FunctionDecl *> exported_functions, set<FunctionDecl *> functions) :
		generator(SM, exported_types, exported_functions, functions)
{
	set_construction_types();
	copy_super_methods();
}

/* Copy the method called "name" described by "fd" from "super" to "clazz"
 * with the distance to the original ancestor given by "depth".
 *
 * In particular, keep track of "fd" as well as the superclass
 * from which it was copied and the distance to the original ancestor.
 */
static void copy_method(isl_class &clazz, const isl_class &super,
	const std::string &name, FunctionDecl *fd, int depth)
{
	clazz.methods[name].insert(fd);
	clazz.copied_from.emplace(fd, super);
	clazz.copy_depth.emplace(fd, depth);
}

/* Do "fd1" and "fd2" have the same signature (ignoring the first argument
 * which represents the object class on which the corresponding method
 * gets called).
 */
static bool same_signature(FunctionDecl *fd1, FunctionDecl *fd2)
{
	int n1 = fd1->getNumParams();
	int n2 = fd2->getNumParams();

	if (n1 != n2)
		return false;

	for (int i = 1; i < n1; ++i) {
		ParmVarDecl *p1 = fd1->getParamDecl(i);
		ParmVarDecl *p2 = fd2->getParamDecl(i);

		if (p1->getOriginalType() != p2->getOriginalType())
			return false;
	}

	return true;
}

/* Return the distance between "clazz" and the ancestor
 * from which "fd" got copied.
 * If no distance was recorded, then the method has not been copied
 * but appears in "clazz" itself and so the distance is zero.
 */
static int copy_depth(const isl_class &clazz, FunctionDecl *fd)
{
	if (clazz.copy_depth.count(fd) == 0)
		return 0;
	return clazz.copy_depth.at(fd);
}

/* Is the method derived from "fd", with method name "name" and
 * with distance to the original ancestor "depth",
 * overridden by a method already in "clazz"?
 *
 * A method is considered to have been overridden if there
 * is a method with the same name in "clazz" that has the same signature and
 * that comes from an ancestor closer to "clazz",
 * where an ancestor is closer if the distance in the class hierarchy
 * is smaller or the distance is the same and the ancestor appears
 * closer in the declaration of the type (in which case it gets added first).
 *
 * If a method with the same signature has already been added,
 * but it does not override the method derived from "fd",
 * then this method is removed since it is overridden by "fd".
 */
static bool is_overridden(FunctionDecl *fd, isl_class &clazz,
	const std::string &name, int depth)
{
	if (clazz.methods.count(name) == 0)
		return false;

	for (const auto &m : clazz.methods.at(name)) {
		if (!same_signature(fd, m))
			continue;
		if (copy_depth(clazz, m) <= depth)
			return true;
		clazz.methods[name].erase(m);
		return false;
	}
	return false;
}

/* Add the methods "methods" with method name "name" from "super" to "clazz"
 * provided they have not been overridden by a method already in "clazz".
 *
 * Methods that are static in their original class are not copied.
 */
void cpp_generator::copy_methods(isl_class &clazz, const std::string &name,
	const isl_class &super, const function_set &methods)
{
	for (auto fd : methods) {
		int depth;

		if (method2class(fd)->is_static(fd))
			continue;
		depth = copy_depth(super, fd) + 1;
		if (is_overridden(fd, clazz, name, depth))
			continue;
		copy_method(clazz, super, name, fd, depth);
	}
}

/* Add all methods from "super" to "clazz" that have not been overridden
 * by a method already in "clazz".
 *
 * Look through all groups of methods with the same name.
 */
void cpp_generator::copy_super_methods(isl_class &clazz, const isl_class &super)
{
	for (const auto &kvp : super.methods) {
		const auto &name = kvp.first;
		const auto &methods = kvp.second;

		copy_methods(clazz, name, super, methods);
	}
}

/* Copy methods from the superclasses of "clazz"
 * if an object of this class can be implicitly converted to an object
 * from the superclass, keeping track
 * of the classes that have already been handled in "done".
 *
 * Make sure the superclasses have copied methods from their superclasses first
 * since those methods could be copied further down to this class.
 *
 * Consider the superclass that appears closest to the subclass first.
 */
void cpp_generator::copy_super_methods(isl_class &clazz, set<string> &done)
{
	auto supers = find_superclasses(clazz.type);

	for (const auto &super : supers)
		if (done.count(super) == 0)
			copy_super_methods(classes[super], done);
	done.insert(clazz.name);

	for (const auto &super_name : supers) {
		const auto &super = classes[super_name];

		if (super.construction_types.count(clazz.name) == 0)
			continue;
		copy_super_methods(clazz, super);
	}
}

/* For each (proper) class, copy methods from its superclasses,
 * if an object from the class can be converted to an object
 * from the superclass.
 *
 * Type based subclasses are not considered for now since
 * they do not have any explicit superclasses.
 *
 * Iterate through all (proper) classes and copy methods
 * from their superclasses,
 * unless they have already been determined by a recursive call.
 */
void cpp_generator::copy_super_methods()
{
	set<string> done;

	for (auto &kvp : classes) {
		auto &clazz = kvp.second;

		if (clazz.is_type_subclass())
			continue;
		if (done.count(clazz.name) != 0)
			continue;
		copy_super_methods(clazz, done);
	}
}

/* Print declarations or implementations of constructors.
 *
 * For each isl function that is marked as __isl_constructor,
 * add a corresponding C++ constructor.
 *
 * Example of declarations:
 *
 * 	inline /\* implicit *\/ union_set(basic_set bset);
 * 	inline /\* implicit *\/ union_set(set set);
 * 	inline explicit val(ctx ctx, long i);
 * 	inline explicit val(ctx ctx, const std::string &str);
 */
void cpp_generator::class_printer::print_constructors()
{
	for (const auto &cons : clazz.constructors)
		print_method(Method(clazz, cons));
}

/* Print declarations or definitions for methods in the class.
 */
void cpp_generator::class_printer::print_methods()
{
	for (const auto &kvp : clazz.methods)
		print_method_group(kvp.second, kvp.first);
}

/* Print declarations or implementations for the methods derived from "fd",
 * which sets an enum.
 *
 * A method is generated for each value in the enum, setting
 * the enum to that value.
 */
void cpp_generator::class_printer::print_set_enums(FunctionDecl *fd)
{
	for (const auto &set : clazz.set_enums.at(fd)) {
		EnumMethod method(clazz, fd, set.method_name, set.name);

		print_method(method);
	}
}

/* Print declarations or implementations for methods derived from functions
 * that set an enum.
 */
void cpp_generator::class_printer::print_set_enums()
{
	for (const auto &kvp : clazz.set_enums)
		print_set_enums(kvp.first);
}

/* Update "convert" to reflect the next combination of automatic conversions
 * for the arguments of "fd",
 * returning false if there are no more combinations.
 *
 * In particular, find the last argument for which an automatic
 * conversion function is available mapping to the type of this argument and
 * that is not already marked for conversion.
 * Mark this argument, if any, for conversion and clear the markings
 * of all subsequent arguments.
 * Repeated calls to this method therefore run through
 * all possible combinations.
 *
 * Note that the first function argument is never considered
 * for automatic conversion since this is the argument
 * from which the isl_ctx used in the conversion is extracted.
 */
bool cpp_generator::class_printer::next_variant(FunctionDecl *fd,
	std::vector<bool> &convert)
{
	size_t n = convert.size();

	for (int i = n - 1; i >= 1; --i) {
		ParmVarDecl *param = fd->getParamDecl(i);
		const Type *type = param->getOriginalType().getTypePtr();

		if (generator.conversions.count(type) == 0)
			continue;
		if (convert[i])
			continue;
		convert[i] = true;
		for (size_t j = i + 1; j < n; ++j)
			convert[j] = false;
		return true;
	}

	return false;
}

/* Print a declaration or definition for a method called "name"
 * derived from "fd".
 *
 * If the method was copied from a superclass, then print a definition
 * that calls the corresponding method in the superclass.
 * Otherwise, for methods that are identified as "get" methods, also
 * print a declaration or definition for the method
 * using a name that includes the "get_" prefix.
 *
 * If the generated method is an object method, then check
 * whether any of its arguments can be automatically converted
 * from something else, and, if so, generate a method
 * for each combination of converted arguments.
 * Do so by constructing a ConversionMethod that changes the converted arguments
 * to those of the sources of the conversions.
 *
 * Note that a method may be both copied from a superclass and
 * have arguments that can be automatically converted.
 * In this case, the conversion methods for the arguments
 * call the corresponding method in this class, which
 * in turn will call the method in the superclass.
 */
void cpp_generator::class_printer::print_method_variants(FunctionDecl *fd,
	const std::string &name)
{
	Method method(clazz, fd, name);
	std::vector<bool> convert(method.num_params());

	if (method.clazz.copied_from.count(method.fd) == 0) {
		print_method(method);
		if (clazz.is_get_method(fd))
			print_get_method(fd);
	} else {
		auto super = method.clazz.copied_from.at(method.fd);
		print_method(ConversionMethod(method, super.name));
	}
	if (method.kind != Method::Kind::member_method)
		return;
	while (next_variant(fd, convert)) {
		print_method(ConversionMethod(method, [&] (int pos) {
			return get_param(fd, pos, convert);
		}));
	}
}

/* Given a function declaration representing a method,
 * does this method have a single argument (beyond the object
 * on which the method is called) that corresponds to
 * an isl object?
 */
static bool has_single_isl_argument(FunctionDecl *fd)
{
	ParmVarDecl *param;

	if (fd->getNumParams() != 2)
		return false;

	param = fd->getParamDecl(1);
	return generator::is_isl_type(param->getOriginalType());
}

/* Does the set "methods" contain exactly one function declaration
 * that corresponds to a method of "clazz" itself (i.e., that
 * was not copied from an ancestor)?
 */
static FunctionDecl *single_local(const isl_class &clazz,
	const function_set &methods)
{
	int count = 0;
	FunctionDecl *local;

	for (const auto &fn : methods) {
		if (!clazz.first_arg_matches_class(fn))
			continue;
		++count;
		local = fn;
	}

	return count == 1 ? local : NULL;
}

/* Given a function declaration "fd" for a method called "name"
 * with a single argument representing an isl object,
 * generate declarations or definitions for methods with the same name,
 * but with as argument an isl object of a class that can be implicitly
 * converted to that of the original argument.
 * In particular, generate methods for converting this argument.
 */
void cpp_generator::class_printer::print_descendent_overloads(
	FunctionDecl *fd, const std::string &name)
{
	Method method(clazz, fd, name);
	ParmVarDecl *param = fd->getParamDecl(1);
	QualType type = param->getOriginalType();
	std::string arg = type->getPointeeType().getAsString();

	for (const auto &kvp : generator.classes[arg].construction_types) {
		const auto sub = kvp.second;
		print_method(ConversionMethod(method, [&] (int pos) {
			return sub;
		}));
	}
}

/* Print declarations or definitions for methods called "name"
 * derived from "methods".
 *
 * If want_descendent_overloads signals that variants should be added that take
 * as arguments those types that can be converted to the original argument type
 * through a unary constructor and if only one of the methods in the group
 * was originally defined in "clazz", then effectively add those variants.
 * Only do this for methods with a single (isl object) argument.
 */
void cpp_generator::class_printer::print_method_group(
	const function_set &methods, const std::string &name)
{
	FunctionDecl *local;

	for (const auto &fd : methods)
		print_method_variants(fd, name);
	if (!want_descendent_overloads(methods))
		return;
	local = single_local(clazz, methods);
	if (!local)
		return;
	if (!has_single_isl_argument(local))
		return;
	print_descendent_overloads(local, name);
}

/* Print the use of the argument at position "pos" to "os".
 *
 * Member methods pass the isl object corresponding to "this"
 * as first argument (at position 0).
 * Any other arguments are passed along from the method arguments.
 *
 * If the argument value is loaded from a this pointer, the original
 * value must be preserved and must consequently be copied.  Values that are
 * loaded from method parameters do not need to be preserved, as such values
 * will already be copies of the actual parameters.  It is consequently possible
 * to directly take the pointer from these values, which saves
 * an unnecessary copy.
 *
 * In case the parameter is a callback function, two parameters get printed,
 * a wrapper for the callback function and a pointer to the actual
 * callback function.  The wrapper is expected to be available
 * in a previously declared variable <name>_lambda, while
 * the actual callback function is expected to be stored
 * in a structure called <name>_data.
 * The caller of this function must ensure that these variables exist.
 */
void Method::print_param_use(ostream &os, int pos) const
{
	ParmVarDecl *param = fd->getParamDecl(pos);
	bool load_from_this_ptr = pos == 0 && kind == member_method;
	string name = param->getName().str();
	QualType type = param->getOriginalType();

	if (type->isIntegerType()) {
		os << name;
		return;
	}

	if (generator::is_string(type)) {
		os << name << ".c_str()";
		return;
	}

	if (generator::is_callback(type)) {
		os << name << "_lambda, ";
		os << "&" << name << "_data";
		return;
	}

	if (!load_from_this_ptr)
		os << name << ".";

	if (generator::keeps(param)) {
		os << "get()";
	} else {
		if (load_from_this_ptr)
			os << "copy()";
		else
			os << "release()";
	}
}

/* Does the isl function from which this method is derived
 * modify an object of a subclass based on a type function?
 */
bool Method::is_subclass_mutator() const
{
	return clazz.is_type_subclass() && generator::is_mutator(clazz, fd);
}

/* Return the C++ return type of the method "method".
 *
 * If the corresponding function modifies an object of a subclass, then return
 * the type of this subclass.
 * Otherwise, return the C++ counterpart of the actual return type.
 */
std::string cpp_type_printer::return_type(const Method &method) const
{
	if (method.is_subclass_mutator())
		return cpp_generator::type2cpp(method.clazz);
	else
		return param(-1, method.fd->getReturnType());
}

/* Return the formal parameter at position "pos" of "fd".
 * However, if this parameter should be converted, as indicated
 * by "convert", then return the second formal parameter
 * of the conversion function instead.
 */
ParmVarDecl *cpp_generator::class_printer::get_param(FunctionDecl *fd,
	int pos, const std::vector<bool> &convert)
{
	ParmVarDecl *param = fd->getParamDecl(pos);

	if (!convert[pos])
		return param;
	return generator.conversions[param->getOriginalType().getTypePtr()];
}

/* Print the header for "method", without newline or semicolon,
 * using "type_printer" to print argument and return types.
 *
 * Print the header of a declaration if this->declarations is set,
 * otherwise print the header of a method definition.
 *
 * This function prints headers for member methods, static methods, and
 * constructors, either for their declaration or definition.
 *
 * Member functions are declared as "const", as they do not change the current
 * object, but instead create a new object. They always retrieve the first
 * parameter of the original isl function from the this-pointer of the object,
 * such that only starting at the second parameter the parameters of the
 * original function become part of the method's interface.
 *
 * A function
 *
 * 	__isl_give isl_set *isl_set_intersect(__isl_take isl_set *s1,
 * 		__isl_take isl_set *s2);
 *
 * is translated into:
 *
 * 	inline set intersect(set set2) const
 *
 * For static functions and constructors all parameters of the original isl
 * function are exposed.
 *
 * Parameters of which no copy is required, are passed
 * as const reference, which allows the compiler to optimize the parameter
 * transfer.
 *
 * Constructors are marked as explicit using the C++ keyword 'explicit' or as
 * implicit using a comment in place of the explicit keyword. By annotating
 * implicit constructors with a comment, users of the interface are made
 * aware of the potential danger that implicit construction is possible
 * for these constructors, whereas without a comment not every user would
 * know that implicit construction is allowed in absence of an explicit keyword.
 *
 * Note that in case "method" is a ConversionMethod, the argument returned
 * by Method::get_param may be different from the original argument.
 * The name of the argument is, however, derived from the original
 * function argument.
 */
void cpp_generator::class_printer::print_method_header(
	const Method &method, const cpp_type_printer &type_printer)
{
	string rettype_str = type_printer.return_type(method);

	if (declarations) {
		os << "  ";

		if (method.kind == Method::Kind::static_method)
			os << "static ";

		os << "inline ";

		if (method.kind == Method::Kind::constructor) {
			if (generator.is_implicit_conversion(method))
				os << "/* implicit */ ";
			else
				os << "explicit ";
		}
	}

	if (method.kind != Method::Kind::constructor)
		os << rettype_str << " ";

	if (!declarations)
		os << type_printer.class_type(cppstring) << "::";

	if (method.kind != Method::Kind::constructor)
		os << method.name;
	else
		os << cppstring;

	method.print_cpp_arg_list(os, [&] (int i) {
		std::string name = method.fd->getParamDecl(i)->getName().str();
		ParmVarDecl *param = method.get_param(i);
		QualType type = param->getOriginalType();
		string cpptype = type_printer.param(i, type);

		if (!method.param_needs_copy(i))
			os << "const " << cpptype << " &" << name;
		else
			os << cpptype << " " << name;
	});

	if (method.kind == Method::Kind::member_method)
		os << " const";
}

/* Generate the list of argument types for a callback function of
 * type "type", appearing in argument position "arg".
 * If "cpp" is set, then generate the C++ type list, otherwise
 * the C type list.
 *
 * For a callback of type
 *
 *      isl_stat (*)(__isl_take isl_map *map, void *user)
 *
 * the following C++ argument list is generated:
 *
 *      map
 *
 * The arguments of the callback are considered to appear
 * after the position of the callback itself.
 */
std::string cpp_type_printer::generate_callback_args(int arg, QualType type,
	bool cpp) const
{
	std::string type_str;
	const FunctionProtoType *callback;
	int num_params;

	callback = generator::extract_prototype(type);
	num_params = callback->getNumArgs();
	if (cpp)
		num_params--;

	for (long i = 0; i < num_params; i++) {
		QualType type = callback->getArgType(i);

		if (cpp)
			type_str += param(arg + 1 + i, type);
		else
			type_str += type.getAsString();

		if (!cpp)
			type_str += "arg_" + ::to_string(i);

		if (i != num_params - 1)
			type_str += ", ";
	}

	return type_str;
}

/* Generate the full cpp type of a callback function of type "type",
 * appearing in argument position "arg".
 *
 * For a callback of type
 *
 *      isl_stat (*)(__isl_take isl_map *map, void *user)
 *
 * the following type is generated:
 *
 *      std::function<stat(map)>
 */
std::string cpp_type_printer::generate_callback_type(int arg, QualType type)
	const
{
	std::string type_str;
	const FunctionProtoType *callback = generator::extract_prototype(type);
	QualType return_type = callback->getReturnType();
	string rettype_str = param(arg, return_type);

	type_str = "std::function<";
	type_str += rettype_str;
	type_str += "(";
	type_str += generate_callback_args(arg, type, true);
	type_str += ")>";

	return type_str;
}

/* An array listing functions that must be renamed and the function name they
 * should be renamed to. We currently rename functions in case their name would
 * match a reserved C++ keyword, which is not allowed in C++.
 */
static const char *rename_map[][2] = {
	{ "union", "unite" },
};

/* Rename method "name" in case the method name in the C++ bindings should not
 * match the name in the C bindings. We do this for example to avoid
 * C++ keywords.
 */
static std::string rename_method(std::string name)
{
	for (size_t i = 0; i < sizeof(rename_map) / sizeof(rename_map[0]); i++)
		if (name.compare(rename_map[i][0]) == 0)
			return rename_map[i][1];

	return name;
}

/* Translate isl class "clazz" to its corresponding C++ type.
 * Use the name of the type based subclass, if any.
 */
string cpp_generator::type2cpp(const isl_class &clazz)
{
	return type2cpp(clazz.subclass_name);
}

/* Translate type string "type_str" to its C++ name counterpart.
*/
string cpp_generator::type2cpp(string type_str)
{
	return type_str.substr(4);
}

/* Return the C++ counterpart to the isl_bool type.
 *
 * By default, this is simply "bool" since
 * the exceptional case is handled through exceptions.
 */
std::string cpp_type_printer::isl_bool() const
{
	return "bool";
}

/* Return the C++ counterpart to the isl_stat type.
 *
 * By default, this is simply "void" since
 * the exceptional case is handled through exceptions.
 */
string cpp_type_printer::isl_stat() const
{
	return "void";
}

/* Return the C++ counterpart to the isl_size type.
 *
 * By default, this is simply "unsigned" since
 * the exceptional case is handled through exceptions.
 */
string cpp_type_printer::isl_size() const
{
	return "unsigned";
}

/* Return the namespace of the generated C++ bindings.
 *
 * By default, this is "isl::".
 */
std::string cpp_type_printer::isl_namespace() const
{
	return "isl::";
}

/* Return the class type given the C++ name.
 *
 * By default, directly use the C++ name.
 */
std::string cpp_type_printer::class_type(const std::string &cpp_name) const
{
	return cpp_name;
}

/* Return the qualified form of the given C++ isl type name appearing
 * in argument position "arg" (-1 for return type).
 *
 * By default, the argument position is ignored.
 */
std::string cpp_type_printer::qualified(int arg, const std::string &cpp_type)
	const
{
	return isl_namespace() + cpp_type;
}

/* Return the C++ counterpart to the given isl type appearing
 * in argument position "arg" (-1 for return type).
 */
std::string cpp_type_printer::isl_type(int arg, QualType type) const
{
	auto name = type->getPointeeType().getAsString();
	return qualified(arg, cpp_generator::type2cpp(name));
}

/* Translate parameter or return type "type" to its C++ name counterpart.
 * "arg" is the position of the argument, or -1 in case of the return type.
 * If any callback is involved, then the return type and arguments types
 * of the callback are considered to start at the position of the callback.
 */
std::string cpp_type_printer::param(int arg, QualType type) const
{
	if (cpp_generator::is_isl_type(type))
		return isl_type(arg, type);

	if (cpp_generator::is_isl_bool(type))
		return isl_bool();

	if (cpp_generator::is_isl_stat(type))
		return isl_stat();

	if (cpp_generator::is_isl_size(type))
		return isl_size();

	if (type->isIntegerType())
		return type.getAsString();

	if (cpp_generator::is_string(type))
		return "std::string";

	if (cpp_generator::is_callback(type))
		return generate_callback_type(arg, type);

	generator::die("Cannot convert type to C++ type");
}

/* Check if "subclass_type" is a subclass of "class_type".
 */
bool cpp_generator::is_subclass(QualType subclass_type,
	const isl_class &class_type)
{
	std::string type_str = subclass_type->getPointeeType().getAsString();
	std::vector<std::string> superclasses;
	std::vector<const isl_class *> parents;
	std::vector<std::string>::iterator ci;

	superclasses = generator::find_superclasses(classes[type_str].type);

	for (ci = superclasses.begin(); ci < superclasses.end(); ci++)
		parents.push_back(&classes[*ci]);

	while (!parents.empty()) {
		const isl_class *candidate = parents.back();

		parents.pop_back();

		if (&class_type == candidate)
			return true;

		superclasses = generator::find_superclasses(candidate->type);

		for (ci = superclasses.begin(); ci < superclasses.end(); ci++)
			parents.push_back(&classes[*ci]);
	}

	return false;
}

/* Check if "cons" is an implicit conversion constructor of class "clazz".
 *
 * An implicit conversion constructor is generated in case "cons" has a single
 * parameter, where the parameter type is a subclass of the class that is
 * currently being generated.
 */
bool cpp_generator::is_implicit_conversion(const Method &cons)
{
	const auto &clazz = cons.clazz;
	ParmVarDecl *param = cons.fd->getParamDecl(0);
	QualType type = param->getOriginalType();

	int num_params = cons.fd->getNumParams();
	if (num_params != 1)
		return false;

	if (is_isl_type(type) && !is_isl_ctx(type) && is_subclass(type, clazz))
		return true;

	return false;
}

/* Get kind of "method" in "clazz".
 *
 * Given the declaration of a static or member method, returns its kind.
 */
static Method::Kind get_kind(const isl_class &clazz, FunctionDecl *method)
{
	if (generator::is_constructor(method))
		return Method::Kind::constructor;
	else if (generator::is_static(clazz, method))
		return Method::Kind::static_method;
	else
		return Method::Kind::member_method;
}

/* Return the callback argument of "fd", if there is any.
 * Return NULL otherwise.
 */
static ParmVarDecl *find_callback_arg(FunctionDecl *fd)
{
	int num_params = fd->getNumParams();

	for (int i = 0; i < num_params; ++i) {
		ParmVarDecl *param = fd->getParamDecl(i);
		if (generator::is_callback(param->getType()))
			return param;
	}

	return NULL;
}

/* Construct a C++ method object from the class to which is belongs,
 * the isl function from which it is derived and the method name.
 *
 * Perform any renaming of the method that may be required and
 * determine the type of the method.
 */
Method::Method(const isl_class &clazz, FunctionDecl *fd,
	const std::string &name) :
		clazz(clazz), fd(fd), name(rename_method(name)),
		kind(get_kind(clazz, fd)),
		callback(find_callback_arg(fd))
{
}

/* Construct a C++ method object from the class to which is belongs and
 * the isl function from which it is derived.
 *
 * Obtain the default method name and continue
 * with the generic constructor.
 */
Method::Method(const isl_class &clazz, FunctionDecl *fd) :
	Method(clazz, fd, clazz.method_name(fd))
{
}

/* Return the number of parameters of the corresponding C function.
 *
 * If the method has a callback argument, we reduce the number of parameters
 * that are exposed by one to hide the user pointer from the interface. On
 * the C++ side no user pointer is needed, as arguments can be forwarded
 * as part of the std::function argument which specifies the callback function.
 *
 * The user pointer is also removed from the number of parameters
 * of the C function because the pair of callback and user pointer
 * is considered as a single argument that is printed as a whole
 * by Method::print_param_use.
 */
int Method::c_num_params() const
{
	return fd->getNumParams() - (callback != NULL);
}

/* Return the number of parameters of the method
 * (including the implicit "this").
 *
 * By default, it is the same as the number of parameters
 * of the corresponding C function.
 */
int Method::num_params() const
{
	return c_num_params();
}

/* Print the arguments from "start" (inclusive) to "end" (exclusive)
 * as arguments to a method of C function call, using "print_arg"
 * to print each individual argument.
 */
void Method::print_arg_list(std::ostream &os, int start, int end,
	const std::function<void(int i)> &print_arg)
{
	os << "(";
	for (int i = start; i < end; ++i) {
		if (i != start)
			os << ", ";
		print_arg(i);
	}
	os << ")";
}

/* Print the arguments to the method call, using "print_arg"
 * to print each individual argument.
 */
void Method::print_cpp_arg_list(std::ostream &os,
	const std::function<void(int i)> &print_arg) const
{
	int first_param = kind == member_method ? 1 : 0;
	print_arg_list(os, first_param, num_params(), print_arg);
}

/* Should the parameter at position "pos" be a copy (rather than
 * a const reference)?
 *
 * Strictly speaking, a copy is only needed on isl types that are
 * not marked __isl_keep, since those will be release()'d
 * by code printed by Method::print_param_use.
 *
 * However, there may be other arguments such as integer types
 * that are more naturally passed as a copy.
 * The default is therefore to require a copy, except for
 * arguments marked __isl_keep, string arguments or callback arguments.
 */
bool Method::param_needs_copy(int pos) const
{
	ParmVarDecl *param = get_param(pos);
	QualType type = param->getOriginalType();

	if (generator::keeps(param))
		return false;
	if (generator::is_string(type) || generator::is_callback(type))
		return false;
	return true;
}

/* Return the method argument at position "pos".
 */
clang::ParmVarDecl *Method::get_param(int pos) const
{
	return fd->getParamDecl(pos);
}

/* Construct a method that performs one or more conversions
 * from the original Method (without conversions),
 * the name of the type to which "this" should be converted and
 * a function for determining the arguments of the constructed method.
 */
ConversionMethod::ConversionMethod(const Method &method,
	const std::string &this_type,
	const std::function<clang::ParmVarDecl *(int pos)> &get_param) :
		NoCopyMethod(method), this_type(this_type),
		get_param_fn(get_param)
{
}

/* Construct a method that only performs a conversion on "this"
 * from the original Method (without conversions) and
 * the name of the type to which "this" should be converted.
 *
 * Call the generic constructor with
 * a function for determining the arguments of the constructed method
 * that performs no conversion.
 */
ConversionMethod::ConversionMethod(const Method &method,
	const std::string &this_type) :
		ConversionMethod(method, this_type, [this] (int pos) {
			return Method::get_param(pos);
		})
{
}

/* Construct a method that performs one or more argument conversions
 * from the original Method (without conversions) and
 * a function for determining the arguments of the constructed method.
 *
 * Call the generic constructor with method.clazz.name as "this" type,
 * indicating that "this" should not be converted.
 */
ConversionMethod::ConversionMethod(const Method &method,
	const std::function<clang::ParmVarDecl *(int pos)> &get_param) :
		ConversionMethod(method, method.clazz.name, get_param)
{
}

/* Should the parameter at position "pos" be a copy (rather than
 * a const reference)?
 *
 * Parameters of isl type do not need to be a copy.
 * For other types, use the same defaults as Method.
 */
bool NoCopyMethod::param_needs_copy(int pos) const
{
	ParmVarDecl *param = get_param(pos);
	QualType type = param->getOriginalType();

	if (generator::is_isl_type(type))
		return false;

	return Method::param_needs_copy(pos);
}

/* Return the method argument at position "pos".
 *
 * Call get_param_fn to determine this argument.
 */
clang::ParmVarDecl *ConversionMethod::get_param(int pos) const
{
	return get_param_fn(pos);
}

/* Print a call to the method (without the arguments),
 * with "ns" the namespace of the generated C++ bindings.
 *
 * If "this_type" is different from the name of the class of the method,
 * then "this" needs to be converted to that type before
 * the call is performed.
 */
void ConversionMethod::print_call(std::ostream &os, const std::string &ns) const
{
	if (clazz.name == this_type) {
		os << "this->";
	} else {
		auto cpp_type = ns + cpp_generator::type2cpp(this_type);
		os << cpp_type << "(*this).";
	}
	os << name;
}

/* Construct an object representing a C++ method for setting an enum
 * from the class to which is belongs,
 * the isl function from which it is derived and the method and enum names.
 */
EnumMethod::EnumMethod(const isl_class &clazz, FunctionDecl *fd,
	const std::string &method_name, const std::string &enum_name) :
		Method(clazz, fd, method_name), enum_name(enum_name)
{
}

/* Print the use of the argument at position "pos" to "os".
 *
 * If the position is beyond the number of method arguments,
 * then it corresponds to the enum value corresponding to this EnumMethod.
 * Otherwise, delegate to Method::print_param_use.
 */
void EnumMethod::print_param_use(ostream &os, int pos) const
{
	if (pos == num_params())
		os << enum_name;
	else
		Method::print_param_use(os, pos);
}

/* Return the number of parameters of the method
 * (including the implicit "this").
 *
 * The last argument of the C function does not appear in the method call,
 * because it is replaced by a break-up into several methods.
 */
int EnumMethod::num_params() const
{
	return Method::num_params() - 1;
}

/* Initialize a class method printer from the stream onto which the methods
 * are printed, the class method description and the C++ interface generator.
 */
cpp_generator::class_printer::class_printer(std::ostream &os,
		const isl_class &clazz, cpp_generator &generator,
		bool declarations) :
	os(os), clazz(clazz), cppstring(type2cpp(clazz)), generator(generator),
	declarations(declarations)
{
}
