예제 #1
0
        private void PropagateRuleTypes(IRRule rule, IRBinaryCondition condition)
        {
            if (condition.LValue.Type == null
                && condition.LValue is IRVariable)
            {
                var lval = condition.LValue as IRVariable;
                var ruleVariable = rule.Variables[lval.Index];
                if (ruleVariable.Type != null)
                {
                    lval.Type = ruleVariable.Type;
                }
            }

            if (condition.RValue.Type == null
                && condition.RValue is IRVariable)
            {
                var rval = condition.RValue as IRVariable;
                var ruleVariable = rule.Variables[rval.Index];
                if (ruleVariable.Type != null)
                {
                    rval.Type = ruleVariable.Type;
                }
            }

            // TODO - handle implicit re-typing of rule variables?
        }
예제 #2
0
        private bool PropagateRuleTypes(IRRule rule, IRBinaryCondition condition)
        {
            bool updated = false;

            if (condition.LValue.Type == null &&
                condition.LValue is IRVariable)
            {
                var lval         = condition.LValue as IRVariable;
                var ruleVariable = rule.Variables[lval.Index];
                if (ruleVariable.Type != null)
                {
                    lval.Type = ruleVariable.Type;
                    updated   = true;
                }
            }

            if (condition.RValue.Type == null &&
                condition.RValue is IRVariable)
            {
                var rval         = condition.RValue as IRVariable;
                var ruleVariable = rule.Variables[rval.Index];
                if (ruleVariable.Type != null)
                {
                    rval.Type = ruleVariable.Type;
                    updated   = true;
                }
            }

            // TODO - handle implicit re-typing of rule variables?

            return(updated);
        }
예제 #3
0
        private UInt32 ComputeTupleSize(IRRule rule, IRBinaryCondition condition, UInt32 lastTupleSize)
        {
            UInt32 tupleSize = lastTupleSize;
            if (condition.LValue is IRVariable)
            {
                var variable = condition.LValue as IRVariable;
                if (variable.Index >= tupleSize)
                {
                    tupleSize = (UInt32)variable.Index + 1;
                }
            }

            if (condition.RValue is IRVariable)
            {
                var variable = condition.RValue as IRVariable;
                if (variable.Index >= tupleSize)
                {
                    tupleSize = (UInt32)variable.Index + 1;
                }
            }

            return tupleSize;
        }
예제 #4
0
        private void VerifyIRBinaryCondition(IRRule rule, IRBinaryCondition condition, Int32 conditionIndex)
        {
            ValueType lhs = condition.LValue.Type, 
                rhs = condition.RValue.Type;

            // Don't raise compiler errors if the untyped value is a variable,
            // as we already have a separate rule-level error for untyped variables.
            if ((lhs == null && condition.LValue is IRVariable)
                || (rhs == null && condition.RValue is IRVariable))
            {
                return;
            }

            if (condition.LValue is IRVariable
                && condition.RValue is IRVariable
                && (condition.LValue as IRVariable).Index == (condition.RValue as IRVariable).Index
                // This bug was fixed in DOS2 DE
                && Game == TargetGame.DOS2
                // There is a known bug in the main campaign that we have to ignore
                && rule.Goal.Name != "EndGame_PrisonersDilemma")
            {
                Context.Log.Error(condition.Location,
                    DiagnosticCode.BinaryOperationSameRhsLhs,
                    "Same variable used on both sides of a binary expression; this will result in an invalid compare in runtime");
                return;
            }

            VerifyIRBinaryConditionValue(rule, condition.LValue, conditionIndex);
            VerifyIRBinaryConditionValue(rule, condition.RValue, conditionIndex);
            
            if (!AreIntrinsicTypesCompatible(lhs.IntrinsicTypeId, rhs.IntrinsicTypeId))
            {
                Context.Log.Error(condition.Location, 
                    DiagnosticCode.LocalTypeMismatch,
                    "Type of left expression ({0}) differs from type of right expression ({1})",
                    TypeToName(lhs.IntrinsicTypeId), TypeToName(rhs.IntrinsicTypeId));
                return;
            }

            if (IsRiskyComparison(lhs.IntrinsicTypeId, rhs.IntrinsicTypeId))
            {
                Context.Log.Error(condition.Location,
                    DiagnosticCode.RiskyComparison,
                    "Comparison between {0} and {1} may trigger incorrect behavior",
                    TypeToName(lhs.IntrinsicTypeId), TypeToName(rhs.IntrinsicTypeId));
                return;
            }

            if (IsGuidAliasToAliasCast(lhs, rhs))
            {
                Context.Log.Error(condition.Location, 
                    DiagnosticCode.GuidAliasMismatch,
                    "GUID alias type of left expression ({0}) differs from type of right expression ({1})",
                    TypeToName(lhs.TypeId), TypeToName(rhs.TypeId));
                return;
            }

            // Using greater than/less than operators for strings and GUIDs is probably a mistake.
            if ((lhs.IntrinsicTypeId == Value.Type.String
                || lhs.IntrinsicTypeId == Value.Type.GuidString)
                && (condition.Op == RelOpType.Greater
                || condition.Op == RelOpType.GreaterOrEqual
                || condition.Op == RelOpType.Less
                || condition.Op == RelOpType.LessOrEqual))
            {
                Context.Log.Warn(condition.Location, 
                    DiagnosticCode.StringLtGtComparison,
                    "String comparison using operator {0} - probably a mistake?", 
                    condition.Op);
                return;
            }
        }