<commit_before>﻿using System;
using System.Linq;
using Lens.SyntaxTree.Compiler;
using Lens.SyntaxTree.Utils;

namespace Lens.SyntaxTree.SyntaxTree.ControlFlow
{
	/// <summary>
	/// A node that represents the lambda function.
	/// </summary>
	public class LambdaNode : FunctionNodeBase
	{
		/// <summary>
		/// The pointer to the method entity defined for this lambda.
		/// </summary>
		private MethodEntity _Method;

		public override void ProcessClosures(Context ctx)
		{
			_Method = ctx.CurrentScope.CreateClosureMethod(ctx, Arguments);
			_Method.Body = Body;

			var methodBackup = ctx.CurrentMethod;
			ctx.CurrentMethod = _Method;

			var scope = _Method.Scope;
			scope.InitializeScope(ctx);
			base.ProcessClosures(ctx);
			
			// get evaluated return type
			var retType = Body.GetExpressionType(ctx);
			_Method.ReturnType = retType;
			_Method.PrepareSelf();

			scope.FinalizeScope(ctx);

			ctx.CurrentMethod = methodBackup;
		}

		protected override Type resolveExpressionType(Context ctx, bool mustReturn = true)
		{
			var retType = Body.GetExpressionType(ctx);
			var argTypes = Arguments.Select(a => a.Type ?? ctx.ResolveType(a.TypeSignature.Signature)).ToArray();
			return retType == typeof (Unit) || retType == typeof(void)
				? FunctionalHelper.CreateActionType(argTypes)
				: FunctionalHelper.CreateFuncType(retType, argTypes);
		}

		public override void Compile(Context ctx, bool mustReturn)
		{
			var gen = ctx.CurrentILGenerator;

			// find constructor
			var retType = Body.GetExpressionType(ctx);
			var type = retType.IsNotVoid()
				? FunctionalHelper.CreateFuncType(retType, _Method.ArgumentTypes)
				: FunctionalHelper.CreateActionType(_Method.ArgumentTypes);
			var ctor = type.GetConstructor(new[] {typeof (object), typeof (IntPtr)});

			var closureInstance = ctx.CurrentScope.ClosureVariable;
			gen.EmitLoadLocal(closureInstance);
			gen.EmitLoadFunctionPointer(_Method.MethodBuilder);
			gen.EmitCreateObject(ctor);
		}
	}
}
<commit_msg>фикс для void-лямбд<commit_after>﻿using System;
using System.Linq;
using Lens.SyntaxTree.Compiler;
using Lens.SyntaxTree.SyntaxTree.Literals;
using Lens.SyntaxTree.Utils;

namespace Lens.SyntaxTree.SyntaxTree.ControlFlow
{
	/// <summary>
	/// A node that represents the lambda function.
	/// </summary>
	public class LambdaNode : FunctionNodeBase
	{
		/// <summary>
		/// The pointer to the method entity defined for this lambda.
		/// </summary>
		private MethodEntity _Method;

		public override void ProcessClosures(Context ctx)
		{
			_Method = ctx.CurrentScope.CreateClosureMethod(ctx, Arguments);
			_Method.Body = Body;

			var methodBackup = ctx.CurrentMethod;
			ctx.CurrentMethod = _Method;

			var scope = _Method.Scope;
			scope.InitializeScope(ctx);
			base.ProcessClosures(ctx);
			
			// get evaluated return type
			var retType = Body.GetExpressionType(ctx);
			if(retType == typeof(NullType))
				Error("Lambda return type cannot be inferred! Please use type casting to specify type.");

			_Method.ReturnType = retType.IsVoid() ? typeof(void) : retType;
			_Method.PrepareSelf();

			scope.FinalizeScope(ctx);

			ctx.CurrentMethod = methodBackup;
		}

		protected override Type resolveExpressionType(Context ctx, bool mustReturn = true)
		{
			var retType = Body.GetExpressionType(ctx);
			var argTypes = Arguments.Select(a => a.Type ?? ctx.ResolveType(a.TypeSignature.Signature)).ToArray();
			return retType == typeof (Unit) || retType == typeof(void)
				? FunctionalHelper.CreateActionType(argTypes)
				: FunctionalHelper.CreateFuncType(retType, argTypes);
		}

		public override void Compile(Context ctx, bool mustReturn)
		{
			var gen = ctx.CurrentILGenerator;

			// find constructor
			var retType = Body.GetExpressionType(ctx);
			var type = retType.IsNotVoid()
				? FunctionalHelper.CreateFuncType(retType, _Method.ArgumentTypes)
				: FunctionalHelper.CreateActionType(_Method.ArgumentTypes);
			var ctor = type.GetConstructor(new[] {typeof (object), typeof (IntPtr)});

			var closureInstance = ctx.CurrentScope.ClosureVariable;
			gen.EmitLoadLocal(closureInstance);
			gen.EmitLoadFunctionPointer(_Method.MethodBuilder);
			gen.EmitCreateObject(ctor);
		}
	}
}

{'fraction_non_alphanumeric': 0.10882563979909113, 'fraction_numerical': 0.0, 'mean_word_length': 4.2209737827715355, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 13, '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': '4038092', 'n_tokens_mistral': 1419, 'n_tokens_neox': 1241, 'n_words': 282}