Ejemplo n.º 1
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.º 2
0
 internal ExprCoalesceNodeForgeEval(
     ExprCoalesceNodeForge forge,
     ExprEvaluator[] evaluators)
 {
     this.forge = forge;
     this.evaluators = evaluators;
 }
Ejemplo n.º 3
0
        public override ExprNode Validate(ExprValidationContext validationContext)
        {
            if (ChildNodes.Length < 2) {
                throw new ExprValidationException("Coalesce node must have at least 2 parameters");
            }

            // get child expression types
            var childTypes = new Type[ChildNodes.Length];
            for (var i = 0; i < ChildNodes.Length; i++) {
                childTypes[i] = ChildNodes[i].Forge.EvaluationType;
            }

            // determine coercion type
            Type resultType;
            try {
                resultType = TypeHelper.GetCommonCoercionType(childTypes);
            }
            catch (CoercionException ex) {
                throw new ExprValidationException("Implicit conversion not allowed: " + ex.Message);
            }

            // determine which child nodes need numeric coercion
            var isNumericCoercion = new bool[ChildNodes.Length];
            for (var i = 0; i < ChildNodes.Length; i++) {
                var node = ChildNodes[i];
                if (node.Forge.EvaluationType.GetBoxedType() != resultType &&
                    node.Forge.EvaluationType != null &&
                    resultType != null) {
                    if (!resultType.IsNumeric()) {
                        throw new ExprValidationException(
                            "Implicit conversion from datatype '" +
                            resultType.CleanName() +
                            "' to " +
                            node.Forge.EvaluationType.CleanName() +
                            " is not allowed");
                    }

                    isNumericCoercion[i] = true;
                }
            }

            forge = new ExprCoalesceNodeForge(this, resultType, isNumericCoercion);
            return null;
        }