Exemple #1
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;
        }
Exemple #2
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;
        }
Exemple #3
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;
        }
Exemple #4
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;
        }
        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);
        }
        public static CodegenExpression Codegen(
            ExprMinMaxRowNodeForge forge,
            CodegenMethodScope codegenMethodScope,
            ExprForgeCodegenSymbol exprSymbol,
            CodegenClassScope codegenClassScope)
        {
            var resultType = forge.EvaluationType;
            var nodes = forge.ForgeRenderable.ChildNodes;

            CodegenExpression expression;
            if (resultType.IsBigInteger()) {
                var convertors = new BigIntegerCoercer[nodes.Length];
                for (var i = 0; i < nodes.Length; i++) {
                    convertors[i] = SimpleNumberCoercerFactory.GetCoercerBigInteger(nodes[i].Forge.EvaluationType);
                }

                expression = MinMaxType.ComputerBigIntCoerce.Codegen(
                    forge.ForgeRenderable.MinMaxTypeEnum == MinMaxTypeEnum.MAX,
                    codegenMethodScope,
                    exprSymbol,
                    codegenClassScope,
                    nodes,
                    convertors);
            }
            else if (resultType.IsDecimal()) {
                if (forge.ForgeRenderable.MinMaxTypeEnum == MinMaxTypeEnum.MAX) {
                    expression = MinMaxType.MaxComputerDecimalCoerce.Codegen(
                        codegenMethodScope,
                        exprSymbol,
                        codegenClassScope,
                        nodes,
                        resultType);
                }
                else {
                    expression = MinMaxType.MinComputerDecimalCoerce.Codegen(
                        codegenMethodScope,
                        exprSymbol,
                        codegenClassScope,
                        nodes,
                        resultType);
                }
            }
            else {
                if (forge.ForgeRenderable.MinMaxTypeEnum == MinMaxTypeEnum.MAX) {
                    expression = MinMaxType.MaxComputerDoubleCoerce.Codegen(
                        codegenMethodScope,
                        exprSymbol,
                        codegenClassScope,
                        nodes,
                        resultType);
                }
                else {
                    expression = MinMaxType.MinComputerDoubleCoerce.Codegen(
                        codegenMethodScope,
                        exprSymbol,
                        codegenClassScope,
                        nodes,
                        resultType);
                }
            }

            return expression;
        }