<commit_before>﻿using System;
using System.Collections.Generic;
using Lens.SyntaxTree.Compiler;
using Lens.SyntaxTree.Translations;
using Lens.SyntaxTree.Utils;

namespace Lens.SyntaxTree.SyntaxTree.ControlFlow
{
	/// <summary>
	/// A conditional expression.
	/// </summary>
	public class IfNode : NodeBase, IStartLocationTrackingEntity
	{
		public IfNode()
		{
			TrueAction = new CodeBlockNode();
		}

		/// <summary>
		/// The condition.
		/// </summary>
		public NodeBase Condition { get; set; }

		/// <summary>
		/// The block of code to be executed if the condition is true.
		/// </summary>
		public CodeBlockNode TrueAction { get; set; }

		/// <summary>
		/// The block of code to be executed if the condition is false.
		/// </summary>
		public CodeBlockNode FalseAction { get; set; }

		public override LexemLocation EndLocation
		{
			get { return FalseAction == null ? TrueAction.EndLocation : FalseAction.EndLocation; }
			set { LocationSetError(); }
		}

		protected override Type resolveExpressionType(Context ctx, bool mustReturn = true)
		{
			if (!mustReturn)
				return typeof (Unit);

			var type = TrueAction.GetExpressionType(ctx);
			if (FalseAction != null)
			{
				var otherType = FalseAction.GetExpressionType(ctx);
				if (otherType.IsExtendablyAssignableFrom(type))
					type = otherType;
				else if(!type.IsExtendablyAssignableFrom(otherType))
					Error(CompilerMessages.ConditionInconsistentTyping, type, otherType);
			}

			return type;
		}

		public override IEnumerable<NodeBase> GetChildNodes()
		{
			yield return Condition;
			yield return TrueAction;
			yield return FalseAction;
		}

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

			var endLabel = gen.DefineLabel();
			var falseLabel = gen.DefineLabel();

			Expr.Cast(Condition, typeof(bool)).Compile(ctx, true);
			if (FalseAction == null)
			{
				gen.EmitBranchFalse(endLabel);
				TrueAction.Compile(ctx, mustReturn);
				gen.MarkLabel(endLabel);
				if(!mustReturn && TrueAction.GetExpressionType(ctx).IsNotVoid())
					gen.EmitPop();
				else
					gen.EmitNop();
			}
			else
			{
				gen.EmitBranchFalse(falseLabel);
				TrueAction.Compile(ctx, mustReturn);

				if (!mustReturn && TrueAction.GetExpressionType(ctx).IsNotVoid())
					gen.EmitPop();

				gen.EmitJump(endLabel);

				gen.MarkLabel(falseLabel);
				FalseAction.Compile(ctx, mustReturn);
				gen.MarkLabel(endLabel);
				if (!mustReturn && FalseAction.GetExpressionType(ctx).IsNotVoid())
					gen.EmitPop();
				else
					gen.EmitNop();
			}
		}

		#region Equality members

		protected bool Equals(IfNode other)
		{
			return Equals(Condition, other.Condition) && Equals(TrueAction, other.TrueAction) && Equals(FalseAction, other.FalseAction);
		}

		public override bool Equals(object obj)
		{
			if (ReferenceEquals(null, obj)) return false;
			if (ReferenceEquals(this, obj)) return true;
			if (obj.GetType() != this.GetType()) return false;
			return Equals((IfNode)obj);
		}

		public override int GetHashCode()<commit_msg>фикс для ifnode<commit_after>﻿using System;
using System.Collections.Generic;
using Lens.SyntaxTree.Compiler;
using Lens.SyntaxTree.Translations;
using Lens.SyntaxTree.Utils;

namespace Lens.SyntaxTree.SyntaxTree.ControlFlow
{
	/// <summary>
	/// A conditional expression.
	/// </summary>
	public class IfNode : NodeBase, IStartLocationTrackingEntity
	{
		public IfNode()
		{
			TrueAction = new CodeBlockNode();
		}

		/// <summary>
		/// The condition.
		/// </summary>
		public NodeBase Condition { get; set; }

		/// <summary>
		/// The block of code to be executed if the condition is true.
		/// </summary>
		public CodeBlockNode TrueAction { get; set; }

		/// <summary>
		/// The block of code to be executed if the condition is false.
		/// </summary>
		public CodeBlockNode FalseAction { get; set; }

		public override LexemLocation EndLocation
		{
			get { return FalseAction == null ? TrueAction.EndLocation : FalseAction.EndLocation; }
			set { LocationSetError(); }
		}

		protected override Type resolveExpressionType(Context ctx, bool mustReturn = true)
		{
			if (!mustReturn || FalseAction == null)
				return typeof (Unit);

			var type = TrueAction.GetExpressionType(ctx);
			var otherType = FalseAction.GetExpressionType(ctx);
			if (otherType.IsExtendablyAssignableFrom(type))
				return otherType;

			if(!type.IsExtendablyAssignableFrom(otherType))
				Error(CompilerMessages.ConditionInconsistentTyping, type, otherType);

			return type;
		}

		public override IEnumerable<NodeBase> GetChildNodes()
		{
			yield return Condition;
			yield return TrueAction;
			yield return FalseAction;
		}

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

			var endLabel = gen.DefineLabel();
			var falseLabel = gen.DefineLabel();

			Expr.Cast(Condition, typeof(bool)).Compile(ctx, true);
			if (FalseAction == null)
			{
				gen.EmitBranchFalse(endLabel);
				TrueAction.Compile(ctx, mustReturn);
				if(TrueAction.GetExpressionType(ctx).IsNotVoid())
					gen.EmitPop();

				gen.MarkLabel(endLabel);
				gen.EmitNop();
			}
			else
			{
				gen.EmitBranchFalse(falseLabel);
				TrueAction.Compile(ctx, mustReturn);

				if (!mustReturn && TrueAction.GetExpressionType(ctx).IsNotVoid())
					gen.EmitPop();

				gen.EmitJump(endLabel);

				gen.MarkLabel(falseLabel);
				FalseAction.Compile(ctx, mustReturn);
				
				if (!mustReturn && FalseAction.GetExpressionType(ctx).IsNotVoid())
					gen.EmitPop();

				gen.MarkLabel(endLabel);
				gen.EmitNop();
			}
		}

		#region Equality members

		protected bool Equals(IfNode other)
		{
			return Equals(Condition, other.Condition) && Equals(TrueAction, other.TrueAction) && Equals(FalseAction, other.FalseAction);
		}

		public override bool Equals(object obj)
		{
			if (ReferenceEquals(null, obj)) return false;
			if (ReferenceEquals(this, obj)) return true;
			if (obj.GetType() != this.GetType()) return false;
			return Equals((IfNode)obj);
		}

		public override int GetHashCode()
{'fraction_non_alphanumeric': 0.11852096401452625, 'fraction_numerical': 0.0, 'mean_word_length': 3.671549730146492, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 21, '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': '2266789', 'n_tokens_mistral': 2207, 'n_tokens_neox': 1845, 'n_words': 440}