예제 #1
0
        private void AddQueryOrProc(IRRule rule)
        {
            // Check if all parameters in the PROC/QRY declaration are typed.
            var procDefn = rule.Conditions[0];
            if (procDefn is IRFuncCondition)
            {
                var def = procDefn as IRFuncCondition;
                FunctionType type;
                switch (rule.Type)
                {
                    case RuleType.Proc: type = FunctionType.Proc; break;
                    case RuleType.Query: type = FunctionType.UserQuery; break;
                    default: throw new InvalidOperationException("Cannot register this type as a PROC or QUERY");
                }

                if (!PropagateSignatureIfRequired(rule, def.Func.Name, type, def.Params, true))
                {
                    // TODO - possibly a warning?
                    /*Context.Log.Error(procDefn.Location, 
                        DiagnosticCode.InvalidProcDefinition,
                        "Signature must be completely typed in declaration of {0} {1}",
                        rule.Type, def.Func.Name);*/
                }
            }
            else
            {
                Context.Log.Error(procDefn.Location, 
                    DiagnosticCode.InvalidProcDefinition,
                    "Declaration of a {0} must start with a {0} name and signature.", 
                    rule.Type);
            }
        }
예제 #2
0
        private IRValue ASTValueToIR(IRRule rule, ASTRValue astValue)
        {
            if (astValue is ASTConstantValue)
            {
                return(ASTConstantToIR(astValue as ASTConstantValue));
            }
            else if (astValue is ASTLocalVar)
            {
                var astVar = astValue as ASTLocalVar;
                // TODO - compiler error if type resolution fails
                var type = astVar.Type != null?Context.LookupType(astVar.Type) : null;

                var ruleVar = rule.FindOrAddVariable(astVar.Name, type);

                return(new IRVariable
                {
                    Index = ruleVar.Index,
                    Type = type,
                    Location = astValue.Location
                });
            }
            else
            {
                throw new InvalidOperationException("Cannot convert unknown AST value type to IR");
            }
        }
예제 #3
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?
        }
예제 #4
0
        private IRRule ASTRuleToIR(IRGoal goal, ASTRule astRule)
        {
            var rule = new IRRule
            {
                Goal            = goal,
                Type            = astRule.Type,
                Conditions      = new List <IRCondition>(astRule.Conditions.Count),
                Actions         = new List <IRStatement>(astRule.Actions.Count),
                Variables       = new List <IRRuleVariable>(),
                VariablesByName = new Dictionary <String, IRRuleVariable>(),
                Location        = astRule.Location
            };

            foreach (var condition in astRule.Conditions)
            {
                rule.Conditions.Add(ASTConditionToIR(rule, condition));
            }

            foreach (var action in astRule.Actions)
            {
                rule.Actions.Add(ASTActionToIR(rule, action));
            }

            return(rule);
        }
예제 #5
0
        private ValueType DetermineSignature(IRRule rule, IRValue value)
        {
            if (value is IRConstant)
            {
                return DetermineSignature(value as IRConstant);
            }
            else if (value is IRVariable)
            {
                if (value.Type != null)
                {
                    return value.Type;
                }

                var irVar = value as IRVariable;
                var ruleVar = rule.Variables[irVar.Index];
                if (ruleVar.Type != null)
                {
                    return ruleVar.Type;
                }
                else
                {
                    return null;
                }
            }
            else
            {
                throw new ArgumentException("Invalid IR value type");
            }
        }
예제 #6
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);
        }
예제 #7
0
        private bool TryPropagateSignature(IRRule rule, FunctionNameAndArity name, FunctionType? type, List<IRValue> parameters, bool allowPartial)
        {
            // Build a signature with all parameters to make sure that all types can be resolved
            var sig = new List<ValueType>(parameters.Count);
            foreach (var param in parameters)
            {
                var paramSignature = DetermineSignature(rule, param);
                if (paramSignature != null)
                {
                    sig.Add(paramSignature);
                }
                else
                {
                    if (allowPartial)
                    {
                        sig.Add(null);
                    }
                    else
                    {
                        return false;
                    }
                }
            }

            // Apply signature to symbol
            return ApplySignature(name, type, sig);
        }
예제 #8
0
        private bool PropagateIRVariableType(IRRule rule, IRVariable variable, ValueType type)
        {
            bool updated = false;
            var  ruleVar = rule.Variables[variable.Index];

            if (ruleVar.Type == null)
            {
                ruleVar.Type = type;
                updated      = true;
            }

            if (variable.Type == null)
            {
                // If a more specific type alias is available from the rule variable, apply the
                // rule type instead of the function argument type
                if (ruleVar.Type.IsAliasOf(type))
                {
                    variable.Type = ruleVar.Type;
                }
                else
                {
                    variable.Type = type;
                }

                updated = true;
            }

            return(updated);
        }
예제 #9
0
 private void VerifyIRValueCall(IRRule rule, IRValue value, FunctionSignature signature, Int32 parameterIndex, 
     Int32 conditionIndex, bool not)
 {
     if (value is IRVariable)
     {
         VerifyIRVariableCall(rule, value as IRVariable, signature, parameterIndex, conditionIndex, not);
     }
 }
예제 #10
0
 private void VerifyIRValue(IRRule rule, IRValue value)
 {
     if (value is IRConstant)
     {
         VerifyIRConstant(value as IRConstant);
     }
     else
     {
         VerifyIRVariable(rule, value as IRVariable);
     }
 }
예제 #11
0
 private void VerifyIRValue(IRRule rule, IRValue value, FunctionSignature func)
 {
     if (value is IRConstant)
     {
         VerifyIRConstant(value as IRConstant);
     }
     else
     {
         VerifyIRVariable(rule, value as IRVariable, func);
     }
 }
예제 #12
0
        private void VerifyIRRule(IRRule rule)
        {
            if (rule.Type == RuleType.Proc || rule.Type == RuleType.Query)
            {
                var initialName = (rule.Conditions[0] as IRFuncCondition).Func.Name;
                if (rule.Type == RuleType.Proc && initialName.Name.Substring(0, 4).ToUpper() != "PROC")
                {
                    Context.Log.Warn(rule.Conditions[0].Location, 
                        DiagnosticCode.RuleNamingStyle,
                        "Name of PROC \"{0}\" should start with the prefix \"PROC\"", 
                        initialName);
                }

                if (rule.Type == RuleType.Query && initialName.Name.Substring(0, 3).ToUpper() != "QRY")
                {
                    Context.Log.Warn(rule.Conditions[0].Location, 
                        DiagnosticCode.RuleNamingStyle,
                        "Name of Query \"{0}\" should start with the prefix \"QRY\"", 
                        initialName);
                }
            }

            for (var i = 0; i < rule.Conditions.Count; i++)
            {
                var condition = rule.Conditions[i];
                if (condition is IRBinaryCondition)
                {
                    VerifyIRBinaryCondition(rule, condition as IRBinaryCondition, i);
                }
                else
                {
                    VerifyIRFuncCondition(rule, condition as IRFuncCondition, i);
                }
            }

            foreach (var action in rule.Actions)
            {
                VerifyIRStatement(rule, action);
            }

            foreach (var variable in rule.Variables)
            {
                if (variable.Type == null)
                {
                    // TODO - return location of first variable reference instead of rule
                    Context.Log.Error(rule.Location, 
                        DiagnosticCode.UnresolvedVariableType,
                        "Variable \"{0}\" of rule could not be typed",
                        variable.Name);
                }
            }
        }
예제 #13
0
        private void VerifyIRVariable(IRRule rule, IRVariable variable, FunctionSignature func)
        {
            var ruleVar = rule.Variables[variable.Index];

            if (variable.Type == null)
            {
                Context.Log.Error(variable.Location,
                                  DiagnosticCode.UnresolvedType,
                                  "Type of variable {0} could not be determined",
                                  ruleVar.Name);
                return;
            }

            if (ruleVar.Type == null)
            {
                Context.Log.Error(variable.Location,
                                  DiagnosticCode.UnresolvedType,
                                  "Type of rule variable {0} could not be determined",
                                  ruleVar.Name);
                return;
            }

            if ((func == null || TypeCoercionWhitelist == null || !TypeCoercionWhitelist.Contains(func.GetNameAndArity().ToString())) &&
                !AllowTypeCoercion)
            {
                if (!AreIntrinsicTypesCompatible(ruleVar.Type.IntrinsicTypeId, variable.Type.IntrinsicTypeId))
                {
                    Context.Log.Error(variable.Location,
                                      DiagnosticCode.CastToUnrelatedType,
                                      "Cannot cast {1} variable {0} to unrelated type {2}",
                                      ruleVar.Name, ruleVar.Type.Name, variable.Type.Name);
                    return;
                }

                if (IsRiskyComparison(ruleVar.Type.IntrinsicTypeId, variable.Type.IntrinsicTypeId))
                {
                    Context.Log.Error(variable.Location,
                                      DiagnosticCode.RiskyComparison,
                                      "Coercion of {1} variable {0} to {2} may trigger incorrect behavior",
                                      ruleVar.Name, ruleVar.Type.Name, variable.Type.Name);
                    return;
                }

                if (IsGuidAliasToAliasCast(ruleVar.Type, variable.Type))
                {
                    Context.Log.Error(variable.Location,
                                      DiagnosticCode.CastToUnrelatedGuidAlias,
                                      "{1} variable {0} converted to unrelated type {2}",
                                      ruleVar.Name, ruleVar.Type.Name, variable.Type.Name);
                }
            }
        }
예제 #14
0
        private void PropagateRuleTypesFromParamList(IRRule rule, List<IRValue> parameters, FunctionSignature signature)
        {
            Int32 index = 0;
            foreach (var param in parameters)
            {
                if (param is IRVariable)
                {
                    var irVar = param as IRVariable;
                    PropagateIRVariableType(rule, param as IRVariable, signature.Params[index].Type);
                }

                index++;
            }
        }
예제 #15
0
파일: Compiler.cs 프로젝트: Rykarix/lslib
        private void VerifyIRVariable(IRRule rule, IRVariable variable)
        {
            var ruleVar = rule.Variables[variable.Index];

            if (variable.Type == null)
            {
                Context.Log.Error(variable.Location,
                                  DiagnosticCode.UnresolvedType,
                                  "Type of variable {0} could not be determined",
                                  ruleVar.Name);
                return;
            }

            if (ruleVar.Type == null)
            {
                Context.Log.Error(variable.Location,
                                  DiagnosticCode.UnresolvedType,
                                  "Type of rule variable {0} could not be determined",
                                  ruleVar.Name);
                return;
            }

            if (!AreIntrinsicTypesCompatible(ruleVar.Type.IntrinsicTypeId, variable.Type.IntrinsicTypeId))
            {
                Context.Log.Error(variable.Location,
                                  DiagnosticCode.CastToUnrelatedType,
                                  "Cannot cast {1} variable {0} to unrelated type {2}",
                                  ruleVar.Name, ruleVar.Type.Name, variable.Type.Name);
                return;
            }

            if (IsRiskyComparison(ruleVar.Type.IntrinsicTypeId, variable.Type.IntrinsicTypeId))
            {
                Context.Log.Error(variable.Location,
                                  DiagnosticCode.RiskyComparison,
                                  "Coercion of {1} variable {0} to {2} may trigger incorrect behavior",
                                  ruleVar.Name, ruleVar.Type.Name, variable.Type.Name);
                return;
            }

            if (IsGuidAliasToAliasCast(ruleVar.Type, variable.Type))
            {
                Context.Log.Error(variable.Location,
                                  DiagnosticCode.CastToUnrelatedGuidAlias,
                                  "{1} variable {0} converted to unrelated type {2}",
                                  ruleVar.Name, ruleVar.Type.Name, variable.Type.Name);
            }
        }
예제 #16
0
        private void VerifyIRBinaryConditionValue(IRRule rule, IRValue value, Int32 conditionIndex)
        {
            VerifyIRValue(rule, value);

            if (value is IRVariable)
            {
                var variable = value as IRVariable;
                var ruleVar = rule.Variables[variable.Index];
                if (ruleVar.FirstBindingIndex == -1 || ruleVar.FirstBindingIndex >= conditionIndex)
                {
                    Context.Log.Error(variable.Location, 
                        DiagnosticCode.ParamNotBound,
                        "Variable {0} is not bound (when used in a binary expression)", 
                        ruleVar.Name);
                }
            }
        }
예제 #17
0
        private bool PropagateSignatureIfRequired(IRRule rule, FunctionNameAndArity name, FunctionType? type, List<IRValue> parameters, bool allowPartial)
        {
            var signature = Context.LookupSignature(name);
            bool signatureOk = (signature != null && signature.FullyTyped);
            if (!signatureOk && TryPropagateSignature(rule, name, type, parameters, allowPartial))
            {
                signature = Context.LookupSignature(name);
                signatureOk = signature.FullyTyped;
            }

            if (signatureOk)
            {
                PropagateRuleTypesFromParamList(rule, parameters, signature);
            }

            return signatureOk;
        }
예제 #18
0
        private bool PropagateRuleTypes(IRRule rule)
        {
            bool updated = false;

            Int32 lastTupleSize = 0;

            foreach (var condition in rule.Conditions)
            {
                if (condition is IRFuncCondition)
                {
                    var func = condition as IRFuncCondition;
                    PropagateSignatureIfRequired(rule, func.Func.Name, null, func.Params, false, ref updated);
                    if (func.TupleSize == -1)
                    {
                        func.TupleSize = ComputeTupleSize(rule, func, lastTupleSize);
                        updated        = true;
                    }
                }
                else
                {
                    var bin = condition as IRBinaryCondition;
                    if (PropagateRuleTypes(rule, bin))
                    {
                        updated = true;
                    }

                    if (bin.TupleSize == -1)
                    {
                        bin.TupleSize = ComputeTupleSize(rule, bin, lastTupleSize);
                        updated       = true;
                    }
                }

                lastTupleSize = condition.TupleSize;
            }

            foreach (var action in rule.Actions)
            {
                if (action.Func != null)
                {
                    PropagateSignatureIfRequired(rule, action.Func.Name, null, action.Params, false, ref updated);
                }
            }

            return(updated);
        }
예제 #19
0
        private UInt32 ComputeTupleSize(IRRule rule, IRFuncCondition condition, UInt32 lastTupleSize)
        {
            UInt32 tupleSize = lastTupleSize;
            foreach (var param in condition.Params)
            {
                if (param is IRVariable)
                {
                    var variable = param as IRVariable;
                    if (variable.Index >= tupleSize)
                    {
                        tupleSize = (UInt32)variable.Index + 1;
                    }
                }
            }

            return tupleSize;
        }
예제 #20
0
        private bool PropagateRuleTypesFromParamList(IRRule rule, List <IRValue> parameters, FunctionSignature signature)
        {
            bool  updated = false;
            Int32 index   = 0;

            foreach (var param in parameters)
            {
                if (param is IRVariable)
                {
                    var irVar = param as IRVariable;
                    if (PropagateIRVariableType(rule, param as IRVariable, signature.Params[index].Type))
                    {
                        updated = true;
                    }
                }

                index++;
            }

            return(updated);
        }
예제 #21
0
        private IRValue ASTValueToIR(IRRule rule, ASTRValue astValue)
        {
            if (astValue is ASTConstantValue)
            {
                return(ASTConstantToIR(astValue as ASTConstantValue));
            }
            else if (astValue is ASTLocalVar)
            {
                var astVar = astValue as ASTLocalVar;
                // TODO - compiler error if type resolution fails
                ValueType type;
                if (astVar.Type != null)
                {
                    type = Context.LookupType(astVar.Type);
                    if (type == null)
                    {
                        Context.Log.Error(astVar.Location, DiagnosticCode.UnresolvedType,
                                          String.Format("Type \"{0}\" does not exist", astVar.Type));
                    }
                }
                else
                {
                    type = null;
                }

                var ruleVar = rule.FindOrAddVariable(astVar.Name, type);

                return(new IRVariable
                {
                    Index = ruleVar.Index,
                    Type = type,
                    Location = astValue.Location
                });
            }
            else
            {
                throw new InvalidOperationException("Cannot convert unknown AST value type to IR");
            }
        }
예제 #22
0
        private IRCondition ASTConditionToIR(IRRule rule, ASTCondition astCondition)
        {
            if (astCondition is ASTFuncCondition)
            {
                var astFunc = astCondition as ASTFuncCondition;
                var func    = new IRFuncCondition
                {
                    Func      = new IRSymbolRef(new FunctionNameAndArity(astFunc.Name, astFunc.Params.Count)),
                    Not       = astFunc.Not,
                    Params    = new List <IRValue>(astFunc.Params.Count),
                    TupleSize = -1,
                    Location  = astCondition.Location
                };

                foreach (var param in astFunc.Params)
                {
                    func.Params.Add(ASTValueToIR(rule, param));
                }

                return(func);
            }
            else if (astCondition is ASTBinaryCondition)
            {
                var astBin = astCondition as ASTBinaryCondition;
                return(new IRBinaryCondition
                {
                    LValue = ASTValueToIR(rule, astBin.LValue),
                    Op = astBin.Op,
                    RValue = ASTValueToIR(rule, astBin.RValue),
                    TupleSize = -1,
                    Location = astCondition.Location
                });
            }
            else
            {
                throw new InvalidOperationException("Cannot convert unknown AST condition type to IR");
            }
        }
예제 #23
0
        private IRStatement ASTActionToIR(IRRule rule, ASTAction astAction)
        {
            if (astAction is ASTGoalCompletedAction)
            {
                var astGoal = astAction as ASTGoalCompletedAction;
                return(new IRStatement
                {
                    Func = null,
                    Goal = rule.Goal,
                    Not = false,
                    Params = new List <IRValue>(),
                    Location = astAction.Location
                });
            }
            else if (astAction is ASTStatement)
            {
                var astStmt = astAction as ASTStatement;
                var stmt    = new IRStatement
                {
                    Func     = new IRSymbolRef(new FunctionNameAndArity(astStmt.Name, astStmt.Params.Count)),
                    Goal     = null,
                    Not      = astStmt.Not,
                    Params   = new List <IRValue>(astStmt.Params.Count),
                    Location = astAction.Location
                };

                foreach (var param in astStmt.Params)
                {
                    stmt.Params.Add(ASTValueToIR(rule, param));
                }

                return(stmt);
            }
            else
            {
                throw new InvalidOperationException("Cannot convert unknown AST condition type to IR");
            }
        }
예제 #24
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;
        }
예제 #25
0
        private void VerifyIRStatement(IRRule rule, IRStatement statement)
        {
            if (statement.Func == null) return;

            var func = Context.LookupSignature(statement.Func.Name);
            if (func == null)
            {
                Context.Log.Error(statement.Location, 
                    DiagnosticCode.UnresolvedSymbol,
                    "Symbol \"{0}\" could not be resolved", 
                    statement.Func.Name);
                return;
            }

            if (!func.FullyTyped)
            {
                Context.Log.Error(statement.Location, 
                    DiagnosticCode.UnresolvedSignature,
                    "Signature of \"{0}\" could not be determined", 
                    statement.Func.Name);
                return;
            }

            if (func.Type != FunctionType.Database
                && func.Type != FunctionType.Call
                && func.Type != FunctionType.SysCall
                && func.Type != FunctionType.Proc)
            {
                Context.Log.Error(statement.Location, 
                    DiagnosticCode.InvalidSymbolInStatement,
                    "KB rule actions can only reference databases, calls and PROCs; \"{0}\" is a {1}",
                    statement.Func.Name, func.Type);
                return;
            }

            if (statement.Not
                && func.Type != FunctionType.Database)
            {
                Context.Log.Error(statement.Location,
                    DiagnosticCode.CanOnlyDeleteFromDatabase,
                    "KB rule NOT actions can only reference databases; \"{0}\" is a {1}",
                    statement.Func.Name, func.Type);
                return;
            }

            if (statement.Not)
            {
                func.Deleted = true;
            }
            else
            {
                func.Inserted = true;
            }

            int index = 0;
            foreach (var param in func.Params)
            {
                var ele = statement.Params[index];

                ValueType type = ele.Type;
                if (type == null)
                {
                    Context.Log.Error(ele.Location, 
                        DiagnosticCode.InternalError,
                        "No type information available for statement argument");
                    continue;
                }
                
                VerifyIRValue(rule, ele);
                VerifyIRValueCall(rule, ele, func, index, -1, statement.Not);
                VerifyParamCompatibility(func, index, param, ele);

                index++;
            }
        }
예제 #26
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;
            }
        }
예제 #27
0
        private void VerifyIRFuncCondition(IRRule rule, IRFuncCondition condition, int conditionIndex)
        {
            // TODO - Merge FuncCondition and IRStatement base?
            // Base --> IRParameterizedCall --> FuncCond: has (NOT) field
            var func = Context.LookupSignature(condition.Func.Name);
            if (func == null)
            {
                Context.Log.Error(condition.Location, 
                    DiagnosticCode.UnresolvedSymbol, 
                    "Symbol \"{0}\" could not be resolved", 
                    condition.Func.Name);
                return;
            }

            if (!func.FullyTyped)
            {
                Context.Log.Error(condition.Location, 
                    DiagnosticCode.UnresolvedSignature,
                    "Signature of \"{0}\" could not be determined", 
                    condition.Func.Name);
                return;
            }

            func.Read = true;

            if (conditionIndex == 0)
            {
                switch (rule.Type)
                {
                    case RuleType.Proc:
                        if (func.Type != FunctionType.Proc)
                        {
                            Context.Log.Error(condition.Location, 
                                DiagnosticCode.InvalidSymbolInInitialCondition,
                                "Initial proc condition can only be a PROC name; \"{0}\" is a {1}",
                                condition.Func.Name, func.Type);
                            return;
                        }
                        break;

                    case RuleType.Query:
                        if (func.Type != FunctionType.UserQuery)
                        {
                            Context.Log.Error(condition.Location, 
                                DiagnosticCode.InvalidSymbolInInitialCondition,
                                "Initial query condition can only be a user-defined QRY name; \"{0}\" is a {1}",
                                condition.Func.Name, func.Type);
                            return;
                        }
                        break;

                    case RuleType.Rule:
                        if (func.Type != FunctionType.Event
                            && func.Type != FunctionType.Database)
                        {
                            Context.Log.Error(condition.Location, 
                                DiagnosticCode.InvalidSymbolInInitialCondition,
                                "Initial rule condition can only be an event or a DB; \"{0}\" is a {1}",
                                condition.Func.Name, func.Type);
                            return;
                        }
                        break;

                    default:
                        throw new Exception("Unknown rule type");
                }
            }
            else
            {
                if (func.Type != FunctionType.SysQuery
                    && func.Type != FunctionType.Query
                    && func.Type != FunctionType.Database
                    && func.Type != FunctionType.UserQuery)
                {
                    Context.Log.Error(condition.Location, 
                        DiagnosticCode.InvalidFunctionTypeInCondition,
                        "Subsequent rule conditions can only be queries or DBs; \"{0}\" is a {1}",
                        condition.Func.Name, func.Type);
                    return;
                }
            }

            int index = 0;
            foreach (var param in func.Params)
            {
                var condParam = condition.Params[index];
                ValueType type = condParam.Type;

                if (type == null)
                {
                    Context.Log.Error(condParam.Location, 
                        DiagnosticCode.InternalError,
                        "No type information available for func condition arg");
                    continue;
                }

                VerifyIRValue(rule, condParam);
                VerifyIRValueCall(rule, condParam, func, index, conditionIndex, condition.Not);
                VerifyParamCompatibility(func, index, param, condParam);

                index++;
            }
        }
예제 #28
0
        private void VerifyIRVariableCall(IRRule rule, IRVariable variable, FunctionSignature signature, Int32 parameterIndex, 
            Int32 conditionIndex, bool not)
        {
            var ruleVar = rule.Variables[variable.Index];
            var param = signature.Params[parameterIndex];

            if (param.Direction == ParamDirection.Out && !not)
            {
                Debug.Assert(conditionIndex != -1);
                if (ruleVar.FirstBindingIndex == -1)
                {
                    ruleVar.FirstBindingIndex = conditionIndex;
                }
            }
            else if (
                // We're in the THEN section of a rule, so we cannot bind here
                conditionIndex == -1 
                // NOT conditions never bind, but they allow unbound unused variables
                || (!ruleVar.IsUnused() && not)
                || (
                    // Databases and events always bind
                    signature.Type != FunctionType.Database
                    && signature.Type != FunctionType.Event
                    // PROC/QRYs bind if they're the first condition in a rule
                    && !(rule.Type == RuleType.Proc && conditionIndex == 0 && signature.Type == FunctionType.Proc)
                    && !(rule.Type == RuleType.Query && conditionIndex == 0 && signature.Type == FunctionType.UserQuery)
                    && param.Direction != ParamDirection.Out
                )
            ) {

                if (
                    // The variable was never bound
                    ruleVar.FirstBindingIndex == -1
                    // The variable was bound after this node (so it is still unbound here)
                    || (conditionIndex != -1 && ruleVar.FirstBindingIndex >= conditionIndex)
                ) {
                    object paramName = (param.Name != null) ? (object)param.Name : (parameterIndex + 1);
                    if (!ruleVar.IsUnused())
                    {
                        Context.Log.Error(variable.Location,
                            DiagnosticCode.ParamNotBound,
                            "Variable {0} is not bound here (when used as parameter {1} of {2} \"{3}\")",
                            ruleVar.Name, paramName, signature.Type, signature.GetNameAndArity());
                    }
                    else
                    {
                        Context.Log.Error(variable.Location,
                            DiagnosticCode.ParamNotBound,
                            "Parameter {0} of {1} \"{2}\" requires a variable or constant, not a placeholder",
                            paramName, signature.Type, signature.GetNameAndArity());
                    }
                }
            }
            else
            {
                if (conditionIndex != -1 && ruleVar.FirstBindingIndex == -1 && !not)
                {
                    ruleVar.FirstBindingIndex = conditionIndex;
                }
            }
        }