public void GenerateCode(ComparisonOperationNode node, ICIL_CodeGenerator codeGenerator)
        {
            node.Holder = codeGenerator.DefineVariable();

            codeGenerator.AddLocalVariable(
                new CIL_LocalVariable((Variable)node.Holder));

            GenerateCode(node.OpNode1, codeGenerator);
            GenerateCode(node.OpNode2, codeGenerator);


            switch (node)
            {
            // value comparison
            case MajorEqualNode majorEqual:
                codeGenerator.AddInstruction(
                    new CilMajorEqual((Variable)majorEqual.Holder, node.OpNode1.Holder, node.OpNode2.Holder));
                break;

            case MajorNode major:
                codeGenerator.AddInstruction(
                    new CilMajor((Variable)major.Holder, node.OpNode1.Holder, node.OpNode2.Holder));
                break;

            case MinorEqualNode minorEqual:
                codeGenerator.AddInstruction(
                    new CilMinorEqual((Variable)minorEqual.Holder, node.OpNode1.Holder, node.OpNode2.Holder));
                break;

            case MinorNode minor:
                codeGenerator.AddInstruction(
                    new CilMinor((Variable)minor.Holder, node.OpNode1.Holder, node.OpNode2.Holder));
                break;

            // both
            case EqualNode equal:

                if (equal.IsValueComparison)
                {
                    codeGenerator.AddInstruction(
                        new CilEqualValue((Variable)equal.Holder, node.OpNode1.Holder, node.OpNode2.Holder));
                }
                else
                {
                    codeGenerator.AddInstruction(
                        new CilEqualReference((Variable)equal.Holder, node.OpNode1.Holder, node.OpNode2.Holder));
                }
                break;
            }
        }
        public void CheckSemantic(ComparisonOperationNode node, IScope scope = null)
        {
            CheckSemantic(node.OpNode1, scope);
            CheckSemantic(node.OpNode2, scope);

            switch (node)
            {
            case EqualNode _:

                if (node.OpNode1.ComputedType != node.OpNode2.ComputedType)
                {
                    Logger.LogError(node.Line, node.CharPositionInLine,
                                    $"Operator '{node.Text}' cannot be applied to operands of type '{node.OpNode1.ComputedType}' and {node.OpNode2.ComputedType}");
                    return;
                }

                break;

            default:

                if (node.OpNode1.ComputedType.Name != "Int" || node.OpNode2.ComputedType.Name != "Int")
                {
                    Logger.LogError(node.Line, node.CharPositionInLine,
                                    $"Operator '{node.Text}' cannot be applied to operands of type '{node.OpNode1.ComputedType}' and {node.OpNode2.ComputedType}");
                    return;
                }
                break;
            }

            switch (node.OpNode1.ComputedType.Name)
            {
            case "Int":
            case "Bool":
            case "String":
                node.IsValueComparison = true;
                break;

            default:
                node.IsValueComparison = false;
                break;
            }

            TypeTable.IsDefinedType("Bool", out var booleanType);
            node.ComputedType = booleanType;
        }