private ParseErrorExpression ExecuteAchievementComparison(ComparisonExpression comparison, InterpreterScope scope)
        {
            var left  = comparison.Left;
            var right = comparison.Right;

            if (left.Type == ExpressionType.Comparison || right.Type == ExpressionType.Comparison)
            {
                return(new ParseErrorExpression("comparison did not evaluate to a valid comparison", comparison));
            }

            var context = scope.GetContext <TriggerBuilderContext>();
            var op      = GetRequirementOperator(comparison.Operation);

            var leftField = CreateFieldFromExpression(left);

            if (leftField.Type != FieldType.None)
            {
                var rightField = CreateFieldFromExpression(right);
                if (rightField.Type != FieldType.None)
                {
                    // comparing two constants, convert to always_true or always_false
                    var requirement = new Requirement
                    {
                        Left     = leftField,
                        Operator = op,
                        Right    = rightField,
                    };

                    if (requirement.Evaluate() == true)
                    {
                        context.Trigger.Add(AlwaysTrueFunction.CreateAlwaysTrueRequirement());
                    }
                    else
                    {
                        context.Trigger.Add(AlwaysFalseFunction.CreateAlwaysFalseRequirement());
                    }

                    return(null);
                }

                // swap the operands and operator so the constant is on the right
                var temp = left;
                left  = right;
                right = temp;

                op = Requirement.GetReversedRequirementOperator(op);
            }

            var error = ExecuteAchievementExpression(left, scope);

            if (error != null)
            {
                return(ParseErrorExpression.WrapError(error, "Invalid value", left));
            }

            if (right.Type == ExpressionType.IntegerConstant || right.Type == ExpressionType.FloatConstant)
            {
                var lastRequirement = context.LastRequirement;
                if (lastRequirement.Operator != RequirementOperator.None)
                {
                    // try to rearrange so the last requirement doesn't have a modifier
                    for (int i = context.Trigger.Count - 2; i >= 0; --i)
                    {
                        var requirement = context.Trigger.ElementAt(i);
                        if (requirement.Type == RequirementType.AddSource && requirement.Operator == RequirementOperator.None)
                        {
                            context.Trigger.Remove(lastRequirement);
                            context.Trigger.Add(new Requirement {
                                Left = requirement.Left
                            });
                            requirement.Left     = lastRequirement.Left;
                            requirement.Operator = lastRequirement.Operator;
                            requirement.Right    = lastRequirement.Right;
                            lastRequirement      = context.LastRequirement;
                            break;
                        }

                        if (requirement.Type != RequirementType.AddSource &&
                            requirement.Type != RequirementType.SubSource &&
                            requirement.Type != RequirementType.AddAddress)
                        {
                            break;
                        }
                    }

                    if (lastRequirement.Operator != RequirementOperator.None)
                    {
                        // last requirement still has a modifier, have to add a dummy condition.
                        lastRequirement.Type = RequirementType.AddSource;
                        context.Trigger.Add(new Requirement {
                            Left = new Field {
                                Size = lastRequirement.Left.Size, Type = FieldType.Value, Value = 0
                            }
                        });
                        lastRequirement = context.LastRequirement;
                    }
                }

                lastRequirement.Operator = op;
                lastRequirement.Right    = CreateFieldFromExpression(right);
            }
            else
            {
                error = ExecuteAchievementExpression(right, scope);
                if (error != null)
                {
                    return(ParseErrorExpression.WrapError(error, "Invalid value", right));
                }

                var extraRequirement = context.LastRequirement;
                ((IList <Requirement>)context.Trigger).RemoveAt(context.Trigger.Count - 1);

                var requirement = context.LastRequirement;
                if (requirement != null)
                {
                    if (requirement.Type == RequirementType.AddAddress)
                    {
                        return(HandleAddAddressComparison(comparison, (IList <Requirement>)context.Trigger, op, extraRequirement));
                    }
                    else if (context.Trigger.Count > 1 && context.Trigger.ElementAt(context.Trigger.Count - 2).Type == RequirementType.AddAddress)
                    {
                        // if left side is an AddAddress chain, but right side is a not, we have to keep the
                        // dummy condition to prevent the AddAddress from modifying the memory address on the
                        // right side. integers are handled above.
                        requirement.Type       = RequirementType.AddSource;
                        extraRequirement.Right = extraRequirement.Left;
                        extraRequirement.Left  = new Field {
                            Type = FieldType.Value, Value = 0
                        };
                        extraRequirement.Operator = op;
                        context.Trigger.Add(extraRequirement);
                    }
                    else if (requirement.Operator != RequirementOperator.None)
                    {
                        // if left side is a complex expression (a * 4), add a new dummy condition for the comparison
                        requirement.Type       = RequirementType.AddSource;
                        extraRequirement.Right = extraRequirement.Left;
                        extraRequirement.Left  = new Field {
                            Type = FieldType.Value, Value = 0
                        };
                        extraRequirement.Operator = op;
                        context.Trigger.Add(extraRequirement);
                    }
                    else
                    {
                        // no AddAddress on either side, just merge the conditions
                        requirement.Operator = op;
                        requirement.Right    = extraRequirement.Left;
                    }
                }
            }

            return(null);
        }