public bool RegisterFunction(FunctionSignature signature, object func) { var nameAndArity = signature.GetNameAndArity(); if (Signatures.ContainsKey(nameAndArity)) { Log.Error(null, DiagnosticCode.SignatureAlreadyDefined, String.Format("Signature already registered: {0}({1})", nameAndArity.Name, nameAndArity.Arity)); return(false); } Signatures.Add(nameAndArity, signature); Functions.Add(nameAndArity, func); return(true); }
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; } } }
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); } } }