Ejemplo n.º 1
0
        public static CodegenExpression CodegenEvaluatorWCoerce(
            ExprForge forge,
            Type optCoercionType,
            CodegenMethod method,
            Type generator,
            CodegenClassScope classScope)
        {
            var evaluate = new CodegenExpressionLambda(method.Block)
                .WithParams(PARAMS);
            var evaluator = NewInstance<ProxyExprEvaluator>(evaluate);
            
            //var evaluator = NewAnonymousClass(method.Block, typeof(ExprEvaluator));
            //var evaluate = CodegenMethod.MakeParentNode(typeof(object), generator, classScope)
			//	.AddParam(PARAMS);
            //evaluator.AddMethod("Evaluate", evaluate);

            var result = ConstantNull();
            if (forge.EvaluationType != null) {
                var evalMethod = CodegenLegoMethodExpression.CodegenExpression(forge, method, classScope, true);
                result = LocalMethod(evalMethod, REF_EPS, REF_ISNEWDATA, REF_EXPREVALCONTEXT);

                var forgeEvaluationType = forge.EvaluationType.GetBoxedType();
                if (optCoercionType != null && forgeEvaluationType != optCoercionType.GetBoxedType()) {
                    var coercer = SimpleNumberCoercerFactory.GetCoercer(
                        forgeEvaluationType,
                        optCoercionType.GetBoxedType());
                    evaluate.Block.DeclareVar(forgeEvaluationType, "result", result);
                    result = coercer.CoerceCodegen(Ref("result"), forge.EvaluationType);
                }
            }

            evaluate.Block.BlockReturn(result);
            return evaluator;
        }
Ejemplo n.º 2
0
        public static CodegenExpression Codegen(
            ExprCoalesceNodeForge forge,
            CodegenMethodScope codegenMethodScope,
            ExprForgeCodegenSymbol exprSymbol,
            CodegenClassScope codegenClassScope)
        {
            if (forge.EvaluationType == null) {
                return ConstantNull();
            }

            var methodNode = codegenMethodScope.MakeChild(
                forge.EvaluationType,
                typeof(ExprCoalesceNodeForgeEval),
                codegenClassScope);

            var block = methodNode.Block;
            var num = 0;
            var doneWithReturn = false;
            foreach (var node in forge.ForgeRenderable.ChildNodes) {
                var reftype = node.Forge.EvaluationType.GetBoxedType();
                if (reftype != null) {
                    var refname = "r" + num;
                    block.DeclareVar(
                        reftype,
                        refname,
                        node.Forge.EvaluateCodegen(reftype, methodNode, exprSymbol, codegenClassScope));

                    if (reftype.CanNotBeNull()) {
                        if (!forge.IsNumericCoercion[num]) {
                            block.MethodReturn(Ref(refname));
                            doneWithReturn = true;
                        }
                        else {
                            var coercer = SimpleNumberCoercerFactory.GetCoercer(reftype, forge.EvaluationType);
                            block.MethodReturn(coercer.CoerceCodegen(Ref(refname), reftype));
                            doneWithReturn = true;
                        }

                        break;
                    }

                    var blockIf = block.IfCondition(NotEqualsNull(Ref(refname)));
                    if (!forge.IsNumericCoercion[num]) {
                        blockIf.BlockReturn(Ref(refname));
                    }
                    else {
                        blockIf.BlockReturn(
                            TypeHelper.CoerceNumberBoxedToBoxedCodegen(Ref(refname), reftype, forge.EvaluationType));
                    }
                }

                num++;
            }

            if (!doneWithReturn) {
                block.MethodReturn(ConstantNull());
            }

            return LocalMethod(methodNode);
        }
Ejemplo n.º 3
0
        private static Coercer GetCoercer(
            Type typeOne,
            Type typeTwo)
        {
            // Get the common type such as Bool, String or Double and Long
            Type coercionType;
            bool mustCoerce;
            try {
                coercionType = typeOne.GetCompareToCoercionType(typeTwo);
            }
            catch (CoercionException) {
                throw new ExprValidationException(
                    "Implicit conversion from datatype '" +
                    typeTwo.CleanName() +
                    "' to '" +
                    typeOne.CleanName() +
                    "' is not allowed");
            }

            // Check if we need to coerce
            mustCoerce = false;
            if (coercionType != typeOne.GetBoxedType() ||
                coercionType != typeTwo.GetBoxedType()) {
                if (coercionType.IsNumeric()) {
                    mustCoerce = true;
                }
            }

            return !mustCoerce ? null : SimpleNumberCoercerFactory.GetCoercer(null, coercionType);
        }
Ejemplo n.º 4
0
        private static Computer MakeDecimalComputer(
            MathArithTypeEnum operation,
            Type typeOne,
            Type typeTwo,
            bool divisionByZeroReturnsNull,
            MathContext optionalMathContext)
        {
            if (typeOne.IsDecimal() && typeTwo.IsDecimal())
            {
                if (operation == MathArithTypeEnum.DIVIDE)
                {
                    if (optionalMathContext != null)
                    {
                        return(new DivideDecimalWMathContext(divisionByZeroReturnsNull, optionalMathContext));
                    }

                    return(new DivideDecimal(divisionByZeroReturnsNull));
                }

                return(computers.Get(new MathArithDesc(typeof(decimal?), operation)));
            }

            var convertorOne = SimpleNumberCoercerFactory.GetCoercer(typeOne, typeof(decimal?));
            var convertorTwo = SimpleNumberCoercerFactory.GetCoercer(typeTwo, typeof(decimal?));

            if (operation == MathArithTypeEnum.ADD)
            {
                return(new AddDecimalConvComputer(convertorOne, convertorTwo));
            }

            if (operation == MathArithTypeEnum.SUBTRACT)
            {
                return(new SubtractDecimalConvComputer(convertorOne, convertorTwo));
            }

            if (operation == MathArithTypeEnum.MULTIPLY)
            {
                return(new MultiplyDecimalConvComputer(convertorOne, convertorTwo));
            }

            if (operation == MathArithTypeEnum.DIVIDE)
            {
                if (optionalMathContext == null)
                {
                    return(new DivideDecimalConvComputerNoMathCtx(
                               convertorOne,
                               convertorTwo,
                               divisionByZeroReturnsNull));
                }

                return(new DivideDecimalConvComputerWithMathCtx(
                           convertorOne,
                           convertorTwo,
                           divisionByZeroReturnsNull,
                           optionalMathContext));
            }

            return(new ModuloDouble());
        }
Ejemplo n.º 5
0
        internal static Pair<ExprForge[], ExprEvaluator[]> MakeVarargArrayEval(
            MethodInfo method,
            ExprForge[] childForges)
        {
            var methodParameterTypes = method.GetParameterTypes();
            ExprEvaluator[] evals = new ExprEvaluator[methodParameterTypes.Length];
            ExprForge[] forges = new ExprForge[methodParameterTypes.Length];
            Type varargClass = methodParameterTypes[methodParameterTypes.Length - 1].GetElementType();
            Type varargClassBoxed = varargClass.GetBoxedType();
            if (methodParameterTypes.Length > 1) {
                Array.Copy(childForges, 0, forges, 0, forges.Length - 1);
            }

            int varargArrayLength = childForges.Length - methodParameterTypes.Length + 1;

            // handle passing array along
            if (varargArrayLength == 1) {
                ExprForge lastForge = childForges[methodParameterTypes.Length - 1];
                Type lastReturns = lastForge.EvaluationType;
                if (lastReturns != null && lastReturns.IsArray) {
                    forges[methodParameterTypes.Length - 1] = lastForge;
                    return new Pair<ExprForge[], ExprEvaluator[]>(forges, evals);
                }
            }

            // handle parameter conversion to vararg parameter
            ExprForge[] varargForges = new ExprForge[varargArrayLength];
            Coercer[] coercers = new Coercer[varargForges.Length];
            bool needCoercion = false;
            for (int i = 0; i < varargArrayLength; i++) {
                int childIndex = i + methodParameterTypes.Length - 1;
                Type resultType = childForges[childIndex].EvaluationType;
                varargForges[i] = childForges[childIndex];

                if (resultType == null && varargClass.CanBeNull()) {
                    continue;
                }

                if (TypeHelper.IsSubclassOrImplementsInterface(resultType, varargClass)) {
                    // no need to coerce
                    continue;
                }

                if (resultType.GetBoxedType() != varargClassBoxed) {
                    needCoercion = true;
                    coercers[i] = SimpleNumberCoercerFactory.GetCoercer(resultType, varargClassBoxed);
                }
            }

            ExprForge varargForge = new ExprNodeVarargOnlyArrayForge(
                varargForges,
                varargClass,
                needCoercion ? coercers : null);
            forges[methodParameterTypes.Length - 1] = varargForge;
            evals[methodParameterTypes.Length - 1] = varargForge.ExprEvaluator;
            return new Pair<ExprForge[], ExprEvaluator[]>(forges, evals);
        }
Ejemplo n.º 6
0
        internal static Coercer GetNumberCoercer(
            Type leftType,
            Type rightType,
            string expression)
        {
            var numericCoercionType = leftType.GetBoxedType();
            if (rightType != leftType) {
                if (rightType.IsNumeric()) {
                    if (!rightType.CanCoerce(leftType)) {
                        ThrowConversionError(rightType, leftType, expression);
                    }

                    return SimpleNumberCoercerFactory.GetCoercer(rightType, numericCoercionType);
                }
            }

            return null;
        }
Ejemplo n.º 7
0
        public static CodegenExpression CodegenCoerce(
            CodegenExpression expression,
            Type exprType,
            Type targetType,
            bool alwaysCast)
        {
            if (targetType == null) {
                return expression;
            }

            if (exprType.GetBoxedType() == targetType.GetBoxedType()) {
                return alwaysCast ? Cast(targetType, expression) : expression;
            }

            var coercer = SimpleNumberCoercerFactory.GetCoercer(exprType, targetType.GetBoxedType());
            if (exprType.IsPrimitive || alwaysCast) {
                expression = Cast(exprType.GetBoxedType(), expression);
            }

            return coercer.CoerceCodegen(expression, exprType);
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Resolve a typed value by first looking at the parameter value provider and by using the evaluator if one was provided
        /// or returning the provided default value if no value was found.
        /// </summary>
        /// <param name="name">parameter name</param>
        /// <param name="optionalEvaluator">evaluator</param>
        /// <param name="context">initialization context</param>
        /// <param name="defaultValue">default value</param>
        /// <returns>value</returns>
        public static T ResolveWithDefault<T>(
            string name,
            ExprEvaluator optionalEvaluator,
            T defaultValue,
            DataFlowOpInitializeContext context)
        {
            T resolvedFromProvider = TryParameterProvider<T>(name, context);
            if (resolvedFromProvider != null) {
                return resolvedFromProvider;
            }

            if (optionalEvaluator == null) {
                return defaultValue;
            }

            T result = (T) optionalEvaluator.Evaluate(null, true, context.AgentInstanceContext);
            if (result == null) {
                return defaultValue;
            }

            var clazz = typeof(T);
            if (clazz.GetBoxedType() == result.GetType().GetBoxedType()) {
                return result;
            }

            if (TypeHelper.IsSubclassOrImplementsInterface(result.GetType(), clazz)) {
                return result;
            }

            //if (TypeHelper.IsSubclassOrImplementsInterface(result.GetType().GetBoxedType(), typeof(object))) {
            if (result.GetType().GetBoxedType().IsNumeric()) {
                return (T) SimpleNumberCoercerFactory.GetCoercer(result.GetType(), clazz.GetBoxedType())
                    .CoerceBoxed(result);
            }

            return (T) result;
        }
        private static FilterSpecParamFilterForEvalForge HandleRangeNodeEndpoint(
            ExprNode endpoint,
            IDictionary<string, Pair<EventType, string>> taggedEventTypes,
            IDictionary<string, Pair<EventType, string>> arrayEventTypes,
            ISet<string> allTagNamesOrdered,
            string statementName,
            StatementRawInfo raw,
            StatementCompileTimeServices services)
        {
            // constant
            if (endpoint.Forge.ForgeConstantType.IsCompileTimeConstant) {
                var value = endpoint.Forge.ExprEvaluator.Evaluate(null, true, null);
                if (value == null) {
                    return null;
                }

                if (value is string) {
                    return new FilterForEvalConstantStringForge((string) value);
                }

                return new FilterForEvalConstantDoubleForge(value.AsDouble());
            }

            if (endpoint is ExprContextPropertyNode) {
                var node = (ExprContextPropertyNode) endpoint;
                if (node.Type == typeof(string)) {
                    return new FilterForEvalContextPropStringForge(node.Getter, node.PropertyName);
                }

                return new FilterForEvalContextPropDoubleForge(node.Getter, node.PropertyName);
            }

            if (endpoint.Forge.ForgeConstantType.IsDeployTimeTimeConstant && endpoint is ExprNodeDeployTimeConst) {
                var node = (ExprNodeDeployTimeConst) endpoint;
                if (endpoint.Forge.EvaluationType == typeof(string)) {
                    return new FilterForEvalDeployTimeConstStringForge(node);
                }

                return new FilterForEvalDeployTimeConstDoubleForge(node);
            }

            // or property
            if (endpoint is ExprIdentNode) {
                return GetIdentNodeDoubleEval((ExprIdentNode) endpoint, arrayEventTypes, statementName);
            }

            // or limited expression
            if (FilterSpecCompilerIndexPlannerHelper.HasLevelOrHint(FilterSpecCompilerIndexPlannerHint.VALUECOMPOSITE, raw, services) &&
                IsLimitedValueExpression(endpoint)) {
                var returnType = endpoint.Forge.EvaluationType;
                MatchedEventConvertorForge convertor = GetMatchEventConvertor(endpoint, taggedEventTypes, arrayEventTypes, allTagNamesOrdered);
                if (returnType == typeof(string)) {
                    return new FilterForEvalLimitedExprForge(endpoint, convertor, null);
                }

                var coercer = SimpleNumberCoercerFactory.GetCoercer(returnType, typeof(double?));
                return new FilterForEvalLimitedExprForge(endpoint, convertor, coercer);
            }

            return null;
        }
Ejemplo n.º 10
0
        public override ExprNode Validate(ExprValidationContext validationContext)
        {
            var analysis = AnalyzeCase();

            foreach (var pair in analysis.WhenThenNodeList) {
                if (!IsCase2) {
                    var returnType = pair.First.Forge.EvaluationType;
                    if (returnType != typeof(bool) && returnType != typeof(bool?)) {
                        throw new ExprValidationException("Case node 'when' expressions must return a boolean value");
                    }
                }
            }

            var mustCoerce = false;
            Coercer coercer = null;
            if (IsCase2) {
                // validate we can compare result types
                var comparedTypes = new List<Type>();
                comparedTypes.Add(analysis.OptionalCompareExprNode.Forge.EvaluationType);
                foreach (var pair in analysis.WhenThenNodeList) {
                    comparedTypes.Add(pair.First.Forge.EvaluationType);
                }

                // Determine common denominator type
                try {
                    var coercionType = TypeHelper.GetCommonCoercionType(comparedTypes.ToArray());

                    // Determine if we need to coerce numbers when one type doesn't match any other type
                    if (coercionType.IsNumeric()) {
                        mustCoerce = false;
                        foreach (var comparedType in comparedTypes) {
                            if (comparedType != coercionType) {
                                mustCoerce = true;
                            }
                        }

                        if (mustCoerce) {
                            coercer = SimpleNumberCoercerFactory.GetCoercer(null, coercionType);
                        }
                    }
                }
                catch (CoercionException ex) {
                    throw new ExprValidationException("Implicit conversion not allowed: " + ex.Message);
                }
            }

            // Determine type of each result (then-node and else node) child node expression
            IList<Type> childTypes = new List<Type>();
            IList<IDictionary<string, object>> childMapTypes = new List<IDictionary<string, object>>();
            foreach (var pair in analysis.WhenThenNodeList) {
                if (pair.Second.Forge is ExprTypableReturnForge) {
                    var typableReturn = (ExprTypableReturnForge) pair.Second.Forge;
                    var rowProps = typableReturn.RowProperties;
                    if (rowProps != null) {
                        childMapTypes.Add(rowProps);
                        continue;
                    }
                }

                childTypes.Add(pair.Second.Forge.EvaluationType);
            }

            if (analysis.OptionalElseExprNode != null) {
                if (analysis.OptionalElseExprNode.Forge is ExprTypableReturnForge) {
                    var typableReturn = (ExprTypableReturnForge) analysis.OptionalElseExprNode.Forge;
                    var rowProps = typableReturn.RowProperties;
                    if (rowProps != null) {
                        childMapTypes.Add(rowProps);
                    }
                    else {
                        childTypes.Add(analysis.OptionalElseExprNode.Forge.EvaluationType);
                    }
                }
                else {
                    childTypes.Add(analysis.OptionalElseExprNode.Forge.EvaluationType);
                }
            }

            if (!childMapTypes.IsEmpty() && !childTypes.IsEmpty()) {
                var message =
                    "Case node 'when' expressions require that all results either return a single value or a Map-type (new-operator) value";
                string check;
                var count = -1;
                foreach (var pair in analysis.WhenThenNodeList) {
                    count++;
                    if (pair.Second.Forge.EvaluationType != null &&
                        pair.Second.Forge.EvaluationType.IsNotGenericDictionary()) {
                        check = ", check when-condition number " + count;
                        throw new ExprValidationException(message + check);
                    }
                }

                if (analysis.OptionalElseExprNode != null) {
                    if (analysis.OptionalElseExprNode.Forge.EvaluationType != null &&
                        analysis.OptionalElseExprNode.Forge.EvaluationType.IsNotGenericDictionary()) {
                        check = ", check the else-condition";
                        throw new ExprValidationException(message + check);
                    }
                }

                throw new ExprValidationException(message);
            }

            IDictionary<string, object> mapResultType = null;
            Type resultType = null;
            var isNumericResult = false;
            if (childMapTypes.IsEmpty()) {
                // Determine common denominator type
                try {
                    resultType = TypeHelper
                        .GetCommonCoercionType(childTypes.ToArray())
                        .GetBoxedType();
                    if (resultType.IsNumeric()) {
                        isNumericResult = true;
                    }
                }
                catch (CoercionException ex) {
                    throw new ExprValidationException("Implicit conversion not allowed: " + ex.Message);
                }
            }
            else {
                resultType = typeof(IDictionary<string, object>);
                mapResultType = childMapTypes[0];
                for (var i = 1; i < childMapTypes.Count; i++) {
                    var other = childMapTypes[i];
                    var messageEquals = BaseNestableEventType.IsDeepEqualsProperties(
                        "Case-when number " + i,
                        mapResultType,
                        other);
                    if (messageEquals != null) {
                        throw new ExprValidationException(
                            "Incompatible case-when return types by new-operator in case-when number " +
                            i +
                            ": " +
                            messageEquals.Message,
                            messageEquals);
                    }
                }
            }

            forge = new ExprCaseNodeForge(
                this,
                resultType,
                mapResultType,
                isNumericResult,
                mustCoerce,
                coercer,
                analysis.WhenThenNodeList,
                analysis.OptionalCompareExprNode,
                analysis.OptionalElseExprNode);
            return null;
        }
Ejemplo n.º 11
0
        public override ExprNode Validate(ExprValidationContext validationContext)
        {
            // Must have 2 child nodes
            if (ChildNodes.Length != 2) {
                throw new ExprValidationException(
                    "Invalid use of equals, expecting left-hand side and right-hand side but received " +
                    ChildNodes.Length +
                    " expressions");
            }

            // Must be the same boxed type returned by expressions under this
            var lhs = ChildNodes[0];
            var rhs = ChildNodes[1];
            var typeOne = lhs.Forge.EvaluationType.GetBoxedType();
            var typeTwo = rhs.Forge.EvaluationType.GetBoxedType();

            // Null constants can be compared for any type
            if (typeOne == null || typeTwo == null) {
                _forge = new ExprEqualsNodeForgeNC(this);
                return null;
            }

            if (typeOne.Equals(typeTwo) || typeOne.IsAssignableFrom(typeTwo)) {
                _forge = new ExprEqualsNodeForgeNC(this);
                return null;
            }

            // Get the common type such as Bool, String or Double and Long
            Type coercionType;
            try {
                coercionType = typeOne.GetCompareToCoercionType(typeTwo);
            }
            catch (CoercionException) {
                throw new ExprValidationException(
                    "Implicit conversion from datatype '" +
                    typeTwo.CleanName() +
                    "' to '" +
                    typeOne.CleanName() +
                    "' is not allowed");
            }

            // Check if we need to coerce
            if (coercionType == typeOne.GetBoxedType() &&
                coercionType == typeTwo.GetBoxedType()) {
                _forge = new ExprEqualsNodeForgeNC(this);
            }
            else {
                if (typeOne.IsArray && typeTwo.IsArray) {
                    var typeOneElement = typeOne.GetElementType();
                    var typeTwoElement = typeTwo.GetElementType();
                    // Check to see if we have a "boxed" element trying to compare against an unboxed element.  We can
                    // coerce this with a custom widener.
                    if (typeOneElement.GetBoxedType() == typeTwoElement.GetBoxedType()) {
                        coercionType = typeOneElement.GetBoxedType().MakeArrayType();
                        var coercerLhs = ArrayCoercerFactory.GetCoercer(typeOne, coercionType);
                        var coercerRhs = ArrayCoercerFactory.GetCoercer(typeTwo, coercionType);
                        _forge = new ExprEqualsNodeForgeCoercion(this, coercerLhs, coercerRhs);
                        return null;
                    }
                }

                if (!coercionType.IsNumeric()) {
                    throw new ExprValidationException(
                        "Cannot convert datatype '" +
                        coercionType.CleanName() +
                        "' to a value that fits both type '" +
                        typeOne.CleanName() +
                        "' and type '" +
                        typeTwo.CleanName() +
                        "'");
                }

                var numberCoercerLHS = SimpleNumberCoercerFactory.GetCoercer(typeOne, coercionType);
                var numberCoercerRHS = SimpleNumberCoercerFactory.GetCoercer(typeTwo, coercionType);
                _forge = new ExprEqualsNodeForgeCoercion(this, numberCoercerLHS, numberCoercerRHS);
            }

            return null;
        }
Ejemplo n.º 12
0
        public CodegenExpression EventBeanGetCodegen(
            CodegenExpression beanExpression,
            CodegenMethodScope parent,
            CodegenClassScope classScope)
        {
            CodegenMethod method = parent.MakeChild(typeof(object), this.GetType(), classScope)
                .AddParam(typeof(EventBean), "eventBean");
            method.Block.DeclareVar<EventBean[]>("events", NewArrayWithInit(typeof(EventBean), Ref("eventBean")));

            // method to evaluate expressions and compute hash
            ExprForgeCodegenSymbol exprSymbol = new ExprForgeCodegenSymbol(true, true);
            CodegenMethod exprMethod = method
                .MakeChildWithScope(
                    reflectionMethod.ReturnType,
                    typeof(CodegenLegoMethodExpression),
                    exprSymbol,
                    classScope)
                .AddParam(ExprForgeCodegenNames.PARAMS);

            // generate args
            StaticMethodCodegenArgDesc[] args = AllArgumentExpressions(
                nodes,
                reflectionMethod,
                exprMethod,
                exprSymbol,
                classScope);
            AppendArgExpressions(args, exprMethod.Block);

            // try block
            CodegenBlock tryBlock = exprMethod.Block.TryCatch();
            CodegenExpression invoke = CodegenInvokeExpression(null, reflectionMethod, args, classScope);
            tryBlock.BlockReturn(invoke);

            // exception handling
            AppendCatch(
                tryBlock,
                reflectionMethod,
                statementName,
                reflectionMethod.DeclaringType.CleanName(),
                true,
                args);

            exprMethod.Block.MethodReturn(Constant(0));

            method.Block.DeclareVar(
                reflectionMethod.ReturnType,
                "result",
                LocalMethod(exprMethod, Ref("events"), ConstantTrue(), ConstantNull()));
            if (reflectionMethod.ReturnType.CanBeNull()) {
                method.Block.IfRefNull("result").BlockReturn(Constant(0));
            }

            method.Block.DeclareVar<int>(
                    "value",
                    SimpleNumberCoercerFactory.GetCoercer(reflectionMethod.ReturnType, typeof(int?))
                        .CoerceCodegen(Ref("result"), reflectionMethod.ReturnType))
                .IfCondition(Relational(Ref("value"), CodegenExpressionRelational.CodegenRelational.GE, Constant(0)))
                .BlockReturn(Op(Ref("value"), "%", Constant(granularity)))
                .MethodReturn(Op(Op(Ref("value"), "%", Constant(granularity)), "*", Constant(-1)));
            return LocalMethod(method, beanExpression);
        }
Ejemplo n.º 13
0
        public override ExprNode Validate(ExprValidationContext validationContext)
        {
            // Must have 2 child nodes
            if (ChildNodes.Length < 1) {
                throw new IllegalStateException("Equals group node does not have 1 or more parameters");
            }

            // Must be the same boxed type returned by expressions under this
            Type typeOne = ChildNodes[0].Forge.EvaluationType.GetBoxedType();

            // collections, array or map not supported
            if (typeOne.IsArray || typeOne.IsGenericCollection() || typeOne.IsGenericStringDictionary()) {
                throw new ExprValidationException(
                    "Collection or array comparison is not allowed for the IN, ANY, SOME or ALL keywords");
            }

            IList<Type> comparedTypes = new List<Type>();
            comparedTypes.Add(typeOne);
            var hasCollectionOrArray = false;
            for (var i = 0; i < ChildNodes.Length - 1; i++) {
                var propType = ChildNodes[i + 1].Forge.EvaluationType;
                if (propType == null) {
                    // no action
                }
                else if (propType.IsArray) {
                    hasCollectionOrArray = true;
                    if (propType.GetElementType() != typeof(object)) {
                        comparedTypes.Add(propType.GetElementType());
                    }
                }
                else if (propType.IsGenericCollection()) {
                    hasCollectionOrArray = true;
                }
                else if (propType.IsGenericStringDictionary()) {
                    hasCollectionOrArray = true;
                }
                else {
                    comparedTypes.Add(propType);
                }
            }

            // Determine common denominator type
            Type coercionTypeBoxed;
            try {
                coercionTypeBoxed = TypeHelper.GetCommonCoercionType(comparedTypes.ToArray());
            }
            catch (CoercionException ex) {
                throw new ExprValidationException("Implicit conversion not allowed: " + ex.Message);
            }

            // Check if we need to coerce
            var mustCoerce = false;
            Coercer coercer = null;
            if (coercionTypeBoxed.IsNumeric()) {
                foreach (var compareType in comparedTypes) {
                    if (coercionTypeBoxed != compareType.GetBoxedType()) {
                        mustCoerce = true;
                    }
                }

                if (mustCoerce) {
                    coercer = SimpleNumberCoercerFactory.GetCoercer(null, coercionTypeBoxed.GetBoxedType());
                }
            }

            _forge = new ExprEqualsAllAnyNodeForge(this, mustCoerce, coercer, coercionTypeBoxed, hasCollectionOrArray);
            return null;
        }
Ejemplo n.º 14
0
        public override ExprNode Validate(ExprValidationContext validationContext)
        {
            var length = ChildNodes.Length;

            // Can be an empty array with no content
            if (ChildNodes.Length == 0) {
                forge = new ExprArrayNodeForge(this, typeof(object), CollectionUtil.OBJECTARRAY_EMPTY);
                return null;
            }

            IList<Type> comparedTypes = new List<Type>();
            for (var i = 0; i < length; i++) {
                comparedTypes.Add(ChildNodes[i].Forge.EvaluationType);
            }

            // Determine common denominator type
            Type arrayReturnType = null;
            var mustCoerce = false;
            Coercer coercer = null;
            try {
                arrayReturnType = TypeHelper.GetCommonCoercionType(comparedTypes.ToArray());

                // Determine if we need to coerce numbers when one type doesn't match any other type
                if (arrayReturnType.IsNumeric()) {
                    mustCoerce = false;
                    foreach (var comparedType in comparedTypes) {
                        if (comparedType != arrayReturnType) {
                            mustCoerce = true;
                        }
                    }

                    if (mustCoerce) {
                        coercer = SimpleNumberCoercerFactory.GetCoercer(null, arrayReturnType);
                    }
                }
            }
            catch (CoercionException) {
                // expected, such as mixing String and int values, or types (not boxed) and primitives
                // use Object[] in such cases
            }

            if (arrayReturnType == null) {
                arrayReturnType = typeof(object);
            }

            // Determine if we are dealing with constants only
            var results = new object[length];
            var index = 0;
            foreach (var child in ChildNodes) {
                if (!child.Forge.ForgeConstantType.IsCompileTimeConstant) {
                    results = null; // not using a constant result
                    break;
                }

                results[index] = ChildNodes[index].Forge.ExprEvaluator.Evaluate(null, false, null);
                index++;
            }

            // Copy constants into array and coerce, if required
            Array constantResult = null;
            if (results != null) {
                constantResult = Array.CreateInstance(arrayReturnType, length);
                for (var i = 0; i < length; i++) {
                    if (mustCoerce) {
                        var boxed = results[i];
                        if (boxed != null) {
                            object coercedResult = coercer.CoerceBoxed(boxed);
                            constantResult.SetValue(coercedResult, i);
                        }
                    }
                    else {
                        constantResult.SetValue(results[i], i);
                    }
                }
            }

            forge = new ExprArrayNodeForge(this, arrayReturnType, mustCoerce, coercer, constantResult);
            return null;
        }
Ejemplo n.º 15
0
        public static CodegenExpression CodegenEvaluatorMayMultiKeyWCoerce(
            IList<ExprForge> forges,
            IList<Type> optCoercionTypes,
            CodegenMethod method,
            Type generator,
            CodegenClassScope classScope)
        {
            if (forges.Count == 1) {
                return CodegenEvaluatorWCoerce(
                    forges[0],
                    optCoercionTypes?[0],
                    method,
                    generator,
                    classScope);
            }

            var evaluate = new CodegenExpressionLambda(method.Block).WithParams(PARAMS);
            var evaluator = NewInstance<ProxyExprEvaluator>(evaluate);
            
            //var evaluator = NewAnonymousClass(method.Block, typeof(ExprEvaluator));
            //var evaluate = CodegenMethod.MakeParentNode<object>(generator, classScope).AddParam(PARAMS);
            //evaluator.AddMethod("Evaluate", evaluate);

            var exprSymbol = new ExprForgeCodegenSymbol(true, null);

            var exprMethod = method.MakeChildWithScope(
                    typeof(object),
                    typeof(CodegenLegoMethodExpression),
                    exprSymbol,
                    classScope)
                .AddParam(PARAMS);

            var exprBlock = exprMethod.Block;

            var expressions = new CodegenExpression[forges.Count];
            for (var i = 0; i < forges.Count; i++) {
                expressions[i] = forges[i].EvaluateCodegen(
                        forges[i].EvaluationType,
                        exprMethod,
                        exprSymbol,
                        classScope);
            }

            exprSymbol.DerivedSymbolsCodegen(exprMethod, exprBlock, classScope);

            exprBlock.DeclareVar<object[]>(
                    "values",
                    NewArrayByLength(typeof(object), Constant(forges.Count)))
                .DeclareVar<HashableMultiKey>("valuesMk", NewInstance<HashableMultiKey>(Ref("values")));
            for (var i = 0; i < forges.Count; i++) {
                var result = expressions[i];
                if (optCoercionTypes != null &&
                    forges[i].EvaluationType.GetBoxedType() != optCoercionTypes[i].GetBoxedType()) {
                    var coercer = SimpleNumberCoercerFactory.GetCoercer(
                        forges[i].EvaluationType,
                        optCoercionTypes[i].GetBoxedType());
                    var name = "result_" + i;
                    exprBlock.DeclareVar(forges[i].EvaluationType, name, expressions[i]);
                    result = coercer.CoerceCodegen(Ref(name), forges[i].EvaluationType);
                }

                exprBlock.AssignArrayElement("values", Constant(i), result);
            }

            exprBlock.ReturnMethodOrBlock(Ref("valuesMk"));
            evaluate.Block.ReturnMethodOrBlock(
                LocalMethod(exprMethod, REF_EPS, REF_ISNEWDATA, REF_EXPREVALCONTEXT));

            return evaluator;
        }