<commit_before>#pragma once

#include "specification\access.h"
#include "specification\accessor\buffer.h"
#include "specification\command_group.h"
#include "specification\ranges.h"
#include "common.h"
#include "debug.h"
#include <unordered_map>


namespace cl {
namespace sycl {

// Forward declarations
class kernel;
class queue;

namespace detail {

namespace type_name {

template <typename DataType>
static string_class get();

#define STRING_TYPE_FUNCION(type)	\
template<>							\
static string_class get<type>() {	\
	return #type "*";				\
}

STRING_TYPE_FUNCION(int)
STRING_TYPE_FUNCION(float)

#undef STRING_TYPE_FUNCION

} // namespace type_name


namespace kernel_ {

// Forward declaration
template<class Input>
struct constructor;


class source {
private:
	struct tuple {
		string_class type_name;
		access::mode mode;
		access::target target;
		buffer_base* buffer;
	};

	static int num_kernels;
	int kernel_id;

	string_class kernel_name;
	vector_class<string_class> lines;
	string_class final_code;
	std::unordered_map<string_class, tuple> resources;

	// TODO: Multithreading support
	SYCL_THREAD_LOCAL static source* scope;

	template<class Input>
	friend struct constructor;

	string_class generate_accessor_list() const;

	static void compile_command(queue* q, source src, shared_unique<kernel> kern);
	static void enqueue_task_command(queue* q, shared_unique<kernel> kern);

	source()
		:	kernel_id(++num_kernels),
			kernel_name(string_class("_sycl_kernel_") + std::to_string(kernel_id)) {}

public:
	static bool in_scope();

	string_class get_code();
	shared_unique<kernel> compile() const;
	void write_buffers_to_device() const;
	void enqueue_task(shared_unique<kernel> kern) const;
	void read_buffers_from_device() const;

	template<int dimensions>
	static void enqueue_range_command(queue* q, detail::shared_unique<kernel> kern, range<dimensions> num_work_items) {
		(*kern)->enqueue_range(q, num_work_items);
	}
	template<int dimensions>
	void enqueue_range(shared_unique<kernel> kern, range<dimensions> num_work_items) const {
		cmd_group::add(enqueue_range_command, __func__, kern, num_work_items);
	}


	template <typename DataType, int dimensions, access::mode mode, access::target target>
	static void register_resource(const accessor_core<DataType, dimensions, mode, target>& acc) {
		if(scope == nullptr) {
			//error::report(error::code::NOT_IN_KERNEL_SCOPE);
			return;
		}

		auto name = acc.get_resource_name();
		auto it = scope->resources.find(name);

		if(it == scope->resources.end()) {
			auto buf = (buffer<DataType, dimensions>*) acc.resource();
			scope->resources[name] = { type_name::get<DataType>(), mode, target, buf };
		}
	}

	// TODO: Should be better hidden
	static void add(string_class line) {
		scope->lines.push_back('\t' + line + ';');
	}

	static string_class get_name(access::target target);
};

// Single task invoke
template<>
struct constructor<void> {
	static source get(function_class<void> kern) {<commit_msg>Adding lines of code without a semicolon at the end.<commit_after>#pragma once

#include "specification\access.h"
#include "specification\accessor\buffer.h"
#include "specification\command_group.h"
#include "specification\ranges.h"
#include "common.h"
#include "debug.h"
#include <unordered_map>


namespace cl {
namespace sycl {

// Forward declarations
class kernel;
class queue;

namespace detail {

namespace type_name {

template <typename DataType>
static string_class get();

#define STRING_TYPE_FUNCION(type)	\
template<>							\
static string_class get<type>() {	\
	return #type "*";				\
}

STRING_TYPE_FUNCION(int)
STRING_TYPE_FUNCION(float)

#undef STRING_TYPE_FUNCION

} // namespace type_name


namespace kernel_ {

// Forward declaration
template<class Input>
struct constructor;


class source {
private:
	struct tuple {
		string_class type_name;
		access::mode mode;
		access::target target;
		buffer_base* buffer;
	};

	static int num_kernels;
	int kernel_id;

	string_class kernel_name;
	vector_class<string_class> lines;
	string_class final_code;
	std::unordered_map<string_class, tuple> resources;

	// TODO: Multithreading support
	SYCL_THREAD_LOCAL static source* scope;

	template<class Input>
	friend struct constructor;

	string_class generate_accessor_list() const;

	static void compile_command(queue* q, source src, shared_unique<kernel> kern);
	static void enqueue_task_command(queue* q, shared_unique<kernel> kern);

	source()
		:	kernel_id(++num_kernels),
			kernel_name(string_class("_sycl_kernel_") + std::to_string(kernel_id)) {}

public:
	static bool in_scope();

	string_class get_code();
	shared_unique<kernel> compile() const;
	void write_buffers_to_device() const;
	void enqueue_task(shared_unique<kernel> kern) const;
	void read_buffers_from_device() const;

	template<int dimensions>
	static void enqueue_range_command(queue* q, detail::shared_unique<kernel> kern, range<dimensions> num_work_items) {
		(*kern)->enqueue_range(q, num_work_items);
	}
	template<int dimensions>
	void enqueue_range(shared_unique<kernel> kern, range<dimensions> num_work_items) const {
		cmd_group::add(enqueue_range_command, __func__, kern, num_work_items);
	}


	template <typename DataType, int dimensions, access::mode mode, access::target target>
	static void register_resource(const accessor_core<DataType, dimensions, mode, target>& acc) {
		if(scope == nullptr) {
			//error::report(error::code::NOT_IN_KERNEL_SCOPE);
			return;
		}

		auto name = acc.get_resource_name();
		auto it = scope->resources.find(name);

		if(it == scope->resources.end()) {
			auto buf = (buffer<DataType, dimensions>*) acc.resource();
			scope->resources[name] = { type_name::get<DataType>(), mode, target, buf };
		}
	}

	template <bool auto_end = true>
	static void add(string_class line) {
		scope->lines.push_back('\t' + line + (auto_end ? ';' : ' '));
	}

	static string_class get_name(access::target target);
};

// Single task invoke
template<>
struct constructor<void> {
	static source get(function_class<void> kern) {
{'fraction_non_alphanumeric': 0.1179504242222592, 'fraction_numerical': 0.0, 'mean_word_length': 5.777903043968433, 'pattern_counts': {'":': 0, '<': 54, '<?xml version=': 0, '>': 64, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7642900', 'n_tokens_mistral': 2074, 'n_tokens_neox': 1958, 'n_words': 459}