<commit_before>using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using IFC4;
using System.Globalization;

namespace STEP
{
	public class STEPId
	{
		public int Value {get;set;}

		public STEPId(int value)
		{
			Value = value;
		}
	}

	public class InstanceData
	{
		public int Id{get;set;}
		public Type Type{get;set;}
		public List<object> Parameters{get;set;}

		public List<System.Reflection.ConstructorInfo> ConstructorChain{get;set;}
		public System.Reflection.ConstructorInfo Constructor{get;set;}

		/// <summary>
		/// The BaseIfc instance constructed using this data. 
		/// </summary>
		/// <returns></returns>
		public BaseIfc ConstructedInstance{get;set;}

		public bool HasDependencies
		{
			get
			{
				return Parameters.Any(p=>p is STEPId);
			}
		}

		public InstanceData(int id, Type type, List<object> parameters,System.Reflection.ConstructorInfo ctor, List<System.Reflection.ConstructorInfo> ctorChain = null)
		{
			Id = id;
			Type = type;
			Parameters = parameters;
			Constructor = ctor;
			ConstructorChain = ctorChain;
		}
	}

	public class STEPListener : STEPBaseListener
	{
		private int currId;
		private IEnumerable<Type> enums;
		private IEnumerable<Type> types;

		private Dictionary<int,InstanceData> instanceData;

		public Dictionary<int, InstanceData> InstanceData
		{
			get{return instanceData;}
		}

		public STEPListener()
		{
			instanceData = new Dictionary<int,InstanceData>();

			// Parsing will involve finding many enum values
			// Cache the enum types for lookup during parsing. 
			enums = typeof(Elements.Model).Assembly.GetTypes().Where(t=>t.IsEnum).ToList();

			types = typeof(Elements.Model).Assembly.GetTypes().Where(t=>!t.IsEnum).ToList();
		}

		public override void EnterInstance(STEPParser.InstanceContext context)
		{
			currId = int.Parse(context.Id().GetText().TrimStart('#'));
		}

		public override void EnterConstructor(STEPParser.ConstructorContext context)
		{
			// Only cache an instance if it's an outer instance.
			if(context.Parent is STEPParser.InstanceContext)
			{
				instanceData.Add(currId, ParseConstructor(currId, context));
			}
		}

		private System.Reflection.ConstructorInfo GetConstructorForType(Type required, ref List<System.Reflection.ConstructorInfo> ctorChain, Type fromSTEP = null)
		{
			if(fromSTEP == null || required.IsAssignableFrom(fromSTEP))
			{
				return required.GetConstructors().OrderBy(c=>c.GetParameters().Count()).Last();
			}

			if(typeof(Select).IsAssignableFrom(required))
			{
				System.Reflection.ConstructorInfo ctor;
				if(TypeHasConstructorForSelectChoice(required, fromSTEP, out ctor, ref ctorChain))
				{
					return ctor;
				}
			}

			throw new Exception($"I could not find a constructor which would create a {required} from a {fromSTEP}.");
		}

		internal static bool TypeHasConstructorForSelectChoice(Type t, Type choice, out System.Reflection.ConstructorInfo ctor, ref List<System.Reflection.ConstructorInfo> cTorChain)
		{
			var ctors = t.GetConstructors().ToArray();
			ctor = ctors.FirstOrDefault(c=>c.GetParameters()[0].ParameterType.IsAssignableFrom(choice));
			if(ctor != null)
			{
				// You've found a constructor that takes the choice type.
				return true;
			}

			// No select constructor could be found that could construct the type directly.
			// See if any of the params are selects and test those selects' constructors for a parameter
			// of foundType.
			foreach(var c in ctors.Where(c=>c.GetParameters().Any(p=>typeof(Select).IsAssignableFrom(p.ParameterType))))
			{
				foreach(var p in c.GetParameters())
				{
					if(TypeHasConstructorForSelectChoice(p.ParameterType, choice, out ctor, ref cTorChain))
					{
						cTorChain.Add(c);
						return true;
					}
				}
			}

			return false;
		} 

		private InstanceData ParseConstructor(int id, STEPParser.ConstructorContext context, Type ifcType = null)
		{
			var typeName = context.TypeRef().GetText();
			
			// If a type has been passed in, we're parsing a constructor
			// as a parameter of a constructor.
			if(ifcType == null)
			{
				ifcType = types.FirstOrDefault(t=>t.Name.ToUpper() == typeName);
			}

			if(ifcType == null)
			{
				throw new STEPUnknownTypeException(typeName);
			}

			// Use the constructor which includes all non-optional parameters.
			var ctorChain = new List<System.Reflection.ConstructorInfo>();
			var ctor = GetConstructorForType(ifcType, ref ctorChain, types.FirstOrDefault(t=>t.Name.ToUpper() == typeName));

			if(ctorChain.Any())
			{
				var chain = string.Join("=>", ctorChain.Select(c=>c.DeclaringType.Name));
				//Console.WriteLine($"Found constructor chain of {chain}=>{ctor.DeclaringType.Name}");
			}
			var ctorParams = ctor.GetParameters();
<commit_msg>Write some info.<commit_after>using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using IFC4;
using System.Globalization;

namespace STEP
{
	public class STEPId
	{
		public int Value {get;set;}

		public STEPId(int value)
		{
			Value = value;
		}
	}

	public class InstanceData
	{
		public int Id{get;set;}
		public Type Type{get;set;}
		public List<object> Parameters{get;set;}

		public List<System.Reflection.ConstructorInfo> ConstructorChain{get;set;}
		public System.Reflection.ConstructorInfo Constructor{get;set;}

		/// <summary>
		/// The BaseIfc instance constructed using this data. 
		/// </summary>
		/// <returns></returns>
		public BaseIfc ConstructedInstance{get;set;}

		public bool HasDependencies
		{
			get
			{
				return Parameters.Any(p=>p is STEPId);
			}
		}

		public InstanceData(int id, Type type, List<object> parameters,System.Reflection.ConstructorInfo ctor, List<System.Reflection.ConstructorInfo> ctorChain = null)
		{
			Id = id;
			Type = type;
			Parameters = parameters;
			Constructor = ctor;
			ConstructorChain = ctorChain;
		}
	}

	public class STEPListener : STEPBaseListener
	{
		private int currId;
		private IEnumerable<Type> enums;
		private IEnumerable<Type> types;

		private Dictionary<int,InstanceData> instanceData;

		public Dictionary<int, InstanceData> InstanceData
		{
			get{return instanceData;}
		}

		public STEPListener()
		{
			instanceData = new Dictionary<int,InstanceData>();

			// Parsing will involve finding many enum values
			// Cache the enum types for lookup during parsing. 
			enums = typeof(Elements.Model).Assembly.GetTypes().Where(t=>t.IsEnum).ToList();

			types = typeof(Elements.Model).Assembly.GetTypes().Where(t=>!t.IsEnum).ToList();
		}

		public override void EnterInstance(STEPParser.InstanceContext context)
		{
			currId = int.Parse(context.Id().GetText().TrimStart('#'));
		}

		public override void EnterConstructor(STEPParser.ConstructorContext context)
		{
			// Only cache an instance if it's an outer instance.
			if(context.Parent is STEPParser.InstanceContext)
			{
				instanceData.Add(currId, ParseConstructor(currId, context));
			}
		}

		private System.Reflection.ConstructorInfo GetConstructorForType(Type required, ref List<System.Reflection.ConstructorInfo> ctorChain, Type fromSTEP = null)
		{
			if(fromSTEP == null || required.IsAssignableFrom(fromSTEP))
			{
				return required.GetConstructors().OrderBy(c=>c.GetParameters().Count()).Last();
			}

			if(typeof(Select).IsAssignableFrom(required))
			{
				System.Reflection.ConstructorInfo ctor;
				if(TypeHasConstructorForSelectChoice(required, fromSTEP, out ctor, ref ctorChain))
				{
					return ctor;
				}
			}

			throw new Exception($"I could not find a constructor which would create a {required} from a {fromSTEP}.");
		}

		internal static bool TypeHasConstructorForSelectChoice(Type t, Type choice, out System.Reflection.ConstructorInfo ctor, ref List<System.Reflection.ConstructorInfo> cTorChain)
		{
			var ctors = t.GetConstructors().ToArray();
			ctor = ctors.FirstOrDefault(c=>c.GetParameters()[0].ParameterType.IsAssignableFrom(choice));
			if(ctor != null)
			{
				// You've found a constructor that takes the choice type.
				return true;
			}

			// No select constructor could be found that could construct the type directly.
			// See if any of the params are selects and test those selects' constructors for a parameter
			// of foundType.
			foreach(var c in ctors.Where(c=>c.GetParameters().Any(p=>typeof(Select).IsAssignableFrom(p.ParameterType))))
			{
				foreach(var p in c.GetParameters())
				{
					if(TypeHasConstructorForSelectChoice(p.ParameterType, choice, out ctor, ref cTorChain))
					{
						cTorChain.Add(c);
						return true;
					}
				}
			}

			return false;
		} 

		private InstanceData ParseConstructor(int id, STEPParser.ConstructorContext context, Type ifcType = null)
		{
			//Console.WriteLine($"Parsing constructor {id}.");

			var typeName = context.TypeRef().GetText();
			
			// If a type has been passed in, we're parsing a constructor
			// as a parameter of a constructor.
			if(ifcType == null)
			{
				ifcType = types.FirstOrDefault(t=>t.Name.ToUpper() == typeName);
			}

			if(ifcType == null)
			{
				throw new STEPUnknownTypeException(typeName);
			}

			// Use the constructor which includes all non-optional parameters.
			var ctorChain = new List<System.Reflection.ConstructorInfo>();
			var ctor = GetConstructorForType(ifcType, ref ctorChain, types.FirstOrDefault(t=>t.Name.ToUpper() == typeName));

			if(ctorChain.Any())
			{
				var chain = string.Join("=>", ctorChain.Select(c=>c.DeclaringType.Name));
			}
			var ctorParams = ctor.GetParameters();

{'fraction_non_alphanumeric': 0.1140267678364422, 'fraction_numerical': 0.00042154073137316893, 'mean_word_length': 3.9145520455722425, 'pattern_counts': {'":': 0, '<': 35, '<?xml version=': 0, '>': 58, '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': '4506845', 'n_tokens_mistral': 3360, 'n_tokens_neox': 2836, 'n_words': 704}