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); }
internal ExprCoalesceNodeForgeEval( ExprCoalesceNodeForge forge, ExprEvaluator[] evaluators) { this.forge = forge; this.evaluators = evaluators; }
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; }