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; }
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); }
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); }
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()); }
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); }
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; }
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); }
/// <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; }
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; }
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; }
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 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 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; }
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; }