<commit_before>﻿using Cxxi.Templates;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;

namespace Cxxi
{
	public partial class Generator
	{
		public List<ModuleTransform> Transformations { get; set; }

		Library Library;
		Options Options;

		public Generator(Library library, Options options)
		{
			Transformations = new List<ModuleTransform>();

			Library = library;
			Options = options;
		}

		public void Process()
		{
			TransformModule();
			ProcessModules();
		}

		// Generates the binding code.
		public void Generate()
		{
			GenerateModules();
		}

		int UniqueType = 0;

		void CleanupText(ref string debugText)
		{
			// Strip off newlines from the debug text.
			if (String.IsNullOrWhiteSpace(debugText))
				debugText = String.Empty;

			// TODO: Make this transformation in the output.
			debugText = Regex.Replace(debugText, " ( )+", " ");
			debugText = Regex.Replace(debugText, "\n", "");
		}

		void ProcessType(Declaration type)
		{
			// If after all the transformations the type still does
			// not have a name, then generate one.

			if (String.IsNullOrWhiteSpace(type.Name))
				type.Name = String.Format("UnnamedType{0}", UniqueType++);

			CleanupText(ref type.DebugText);
		}

		void ProcessTypes<T>(List<T> types) where T : Declaration
		{
			foreach (T type in types)
				ProcessType(type);
		}

		void ProcessClasses(List<Class> Classes)
		{
			ProcessTypes(Classes);

			foreach (var @class in Classes)
				ProcessTypes(@class.Fields);
		}

		void ProcessFunctions(List<Function> Functions)
		{
			ProcessTypes(Functions);

			foreach (var function in Functions)
			{
				if (function.ReturnType == null)
				{
					// Ignore and warn about unknown types.
					function.Ignore = true;

					var s = "Function '{0}' was ignored due to unknown return type...";
					Console.WriteLine(String.Format(s, function.Name));
				}

				ProcessTypes(function.Parameters);
			}
		}

		void ProcessModules()
		{
			if (String.IsNullOrEmpty(Library.Name))
				Library.Name = "";

			// Process everything in the global namespace for now.
			foreach (var module in Library.Modules)
			{
				ProcessNamespace(module);
			}
		}

		void ProcessNamespace(Namespace @namespace)
		{
			ProcessTypes(@namespace.Enums);
			ProcessFunctions(@namespace.Functions);
			ProcessClasses(@namespace.Classes);
		}

		void TransformModule()
		{
			if (String.IsNullOrEmpty(Library.Name))
				Library.Name = "";

			// Process everything in the global namespace for now.
			foreach (var module in Library.Modules)
			{
				foreach (Enumeration @enum in module.Enums)
					TransformEnum(@enum);

				foreach (Function function in module.Functions)
					TransformFunction(function);

				foreach (Class @class in module.Classes)
					TransformClass(@class);
			}
		}

		void TransformType(Declaration type)
		{
			foreach (var transform in Transformations)
				transform.ProcessDeclaration(type);
		}

		void TransformClass(Class @class)
		{
			TransformType(@class);

			foreach (var field in @class.Fields)
				TransformType(field);
		}

		void TransformFunction(Function function)
		{
			TransformType(function);

			foreach (var param in function.Parameters)
				TransformType(param);
		}


		void TransformEnum(Enumeration @enum)
		{
			TransformType(@enum);<commit_msg>Hooked up typedef processing to the code generator.<commit_after>﻿using Cxxi.Templates;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;

namespace Cxxi
{
	public partial class Generator
	{
		public List<ModuleTransform> Transformations { get; set; }

		Library Library;
		Options Options;

		public Generator(Library library, Options options)
		{
			Transformations = new List<ModuleTransform>();

			Library = library;
			Options = options;
		}

		public void Process()
		{
			TransformModule();
			ProcessModules();
		}

		// Generates the binding code.
		public void Generate()
		{
			GenerateModules();
		}

		int UniqueName = 0;

		void CleanupText(ref string debugText)
		{
			// Strip off newlines from the debug text.
			if (String.IsNullOrWhiteSpace(debugText))
				debugText = String.Empty;

			// TODO: Make this transformation in the output.
			debugText = Regex.Replace(debugText, " ( )+", " ");
			debugText = Regex.Replace(debugText, "\n", "");
		}

		void ProcessDeclaration(Declaration decl)
		{
			// If after all the transformations the type still does
			// not have a name, then generate one.

			if (string.IsNullOrWhiteSpace(decl.Name))
				decl.Name = string.Format("Unnamed{0}", UniqueName++);

			CleanupText(ref decl.DebugText);
		}

		void ProcessDeclarations<T>(List<T> decls) where T : Declaration
		{
			foreach (T decl in decls)
				ProcessDeclaration(decl);
		}

		void ProcessClasses(List<Class> classes)
		{
			ProcessDeclarations(classes);

			foreach (var @class in classes)
				ProcessDeclarations(@class.Fields);
		}

		void ProcessTypedefs(Namespace @namespace, List<Typedef> typedefs)
		{
			ProcessDeclarations(typedefs);

			foreach (var typedef in typedefs)
			{
				var @class = @namespace.FindClass(typedef.Name);

				// Clang will walk the typedef'd tag type and the typedef decl,
				// so we ignore the class and process just the typedef.

				if (@class != null)
					typedef.Ignore = true;
			}
		}

		void ProcessFunctions(List<Function> Functions)
		{
			ProcessDeclarations(Functions);

			foreach (var function in Functions)
			{
				if (function.ReturnType == null)
				{
					// Ignore and warn about unknown types.
					function.Ignore = true;

					var s = "Function '{0}' was ignored due to unknown return type...";
					Console.WriteLine(String.Format(s, function.Name));
				}

				foreach (var param in function.Parameters)
				{
					ProcessDeclaration(param);
				}
			}
		}

		void ProcessModules()
		{
			if (string.IsNullOrEmpty(Library.Name))
				Library.Name = "";

			// Process everything in the global namespace for now.
			foreach (var module in Library.Modules)
			{
				ProcessNamespace(module);
			}
		}

		void ProcessNamespace(Namespace @namespace)
		{
			ProcessDeclarations(@namespace.Enums);
			ProcessFunctions(@namespace.Functions);
			ProcessClasses(@namespace.Classes);
			ProcessTypedefs(@namespace, @namespace.Typedefs);
		}

		void TransformModule()
		{
			if (string.IsNullOrEmpty(Library.Name))
				Library.Name = string.Empty;

			// Process everything in the global namespace for now.
			foreach (var module in Library.Modules)
			{
				foreach (Enumeration @enum in module.Enums)
					TransformEnum(@enum);

				foreach (Function function in module.Functions)
					TransformFunction(function);

				foreach (Class @class in module.Classes)
					TransformClass(@class);

				foreach (Typedef typedef in module.Typedefs)
					TransformTypedef(typedef);
			}
		}

		void TransformDeclaration(Declaration decl)
		{
			foreach (var transform in Transformations)
				transform.ProcessDeclaration(decl);
		}

		void TransformTypedef(Typedef typedef)
		{
			foreach (var transform in Transformations)
				transform.ProcessDeclaration(typedef);
		}

		void TransformClass(Class @class)
		{
			TransformDeclaration(@class);

			foreach (var field in @class.Fields)
				TransformDeclaration(field);
		}

		void TransformFunction(Function function)
		{
			TransformDeclaration(function);

			foreach (var param in function.Parameters)
				TransformDeclaration(param);
		}


		void TransformEnum(Enumeration @enum)
		{
			TransformDeclaration(@enum);
{'fraction_non_alphanumeric': 0.10415003990422984, 'fraction_numerical': 0.0007980845969672786, 'mean_word_length': 3.472932778108269, 'pattern_counts': {'":': 0, '<': 16, '<?xml version=': 0, '>': 16, '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': '2198019', 'n_tokens_mistral': 2714, 'n_tokens_neox': 2140, 'n_words': 581}