public ExprArrayNodeForgeEval( ExprArrayNodeForge forge, ExprEvaluator[] evaluators) { _forge = forge; _evaluators = evaluators; }
public static CodegenExpression Codegen( ExprArrayNodeForge forge, CodegenMethodScope codegenMethodScope, ExprForgeCodegenSymbol exprSymbol, CodegenClassScope codegenClassScope) { var forgeRenderable = forge.ForgeRenderableArray; var methodNode = codegenMethodScope.MakeChild( forge.EvaluationType, typeof(ExprArrayNodeForgeEval), codegenClassScope); var block = methodNode.Block .DeclareVar( forge.EvaluationType, "array", NewArrayByLength(forge.ArrayReturnType, Constant(forgeRenderable.ChildNodes.Length))); for (var i = 0; i < forgeRenderable.ChildNodes.Length; i++) { var child = forgeRenderable.ChildNodes[i].Forge; var childType = child.EvaluationType; var refname = "r" + i; block.DeclareVar( childType, refname, child.EvaluateCodegen(childType, methodNode, exprSymbol, codegenClassScope)); if (child.EvaluationType.CanNotBeNull()) { if (!forge.IsMustCoerce) { block.AssignArrayElement("array", Constant(i), Ref(refname)); } else { block.AssignArrayElement( "array", Constant(i), forge.Coercer.CoerceCodegen(Ref(refname), child.EvaluationType)); } } else { var ifNotNull = block.IfCondition(NotEqualsNull(Ref(refname))); if (!forge.IsMustCoerce) { ifNotNull.AssignArrayElement("array", Constant(i), Ref(refname)); } else { ifNotNull.AssignArrayElement( "array", Constant(i), forge.Coercer.CoerceCodegen(Ref(refname), child.EvaluationType)); } } } block.MethodReturn(Ref("array")); return LocalMethod(methodNode); }
public static CodegenExpression CodegenEvaluateGetROCollectionScalar( ExprArrayNodeForge forge, CodegenMethodScope codegenMethodScope, ExprForgeCodegenSymbol exprSymbol, CodegenClassScope codegenClassScope) { var children = forge.ForgeRenderableArray.ChildNodes; if (children.Length == 0) { return StaticMethod(typeof(Collections), "GetEmptyList"); } var methodNode = codegenMethodScope.MakeChild( typeof(FlexCollection), typeof(ExprArrayNodeForgeEval), codegenClassScope); var block = methodNode.Block .DeclareVar<ArrayDeque<object>>( "resultList", NewInstance<ArrayDeque<object>>(Constant(children.Length))); var count = -1; foreach (var child in children) { count++; var refname = "r" + count; var childForge = child.Forge; var returnType = childForge.EvaluationType; if (returnType == null) { continue; } block.DeclareVar( returnType, refname, childForge.EvaluateCodegen(returnType, methodNode, exprSymbol, codegenClassScope)); var nonNullTest = returnType.CanNotBeNull() ? ConstantTrue() : NotEqualsNull(Ref(refname)); var blockIfNotNull = block.IfCondition(nonNullTest); CodegenExpression added = Ref(refname); if (forge.IsMustCoerce) { added = forge.Coercer.CoerceCodegen(Ref(refname), childForge.EvaluationType); } blockIfNotNull.Expression(ExprDotMethod(Ref("resultList"), "Add", added)); } block.MethodReturn(FlexWrap(Ref("resultList"))); return LocalMethod(methodNode); }
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 Codegen( ExprArrayNodeForge forge, CodegenMethodScope codegenMethodScope, ExprForgeCodegenSymbol exprSymbol, CodegenClassScope codegenClassScope) { var forgeRenderable = forge.ForgeRenderableArray; var methodNode = codegenMethodScope.MakeChild( forge.EvaluationType, typeof(ExprArrayNodeForgeEval), codegenClassScope); var arrayType = forge.EvaluationType; var block = methodNode.Block .DeclareVar( arrayType, "array", NewArrayByLength(forge.ArrayReturnType, Constant(forgeRenderable.ChildNodes.Length))); var requiresPrimitive = forge.Parent.OptionalRequiredType != null && forge.Parent.OptionalRequiredType.IsPrimitive; for (var i = 0; i < forgeRenderable.ChildNodes.Length; i++) { var child = forgeRenderable.ChildNodes[i].Forge; var childType = child.EvaluationType; var refname = "r" + i; block.DeclareVar( childType, refname, child.EvaluateCodegen(childType, methodNode, exprSymbol, codegenClassScope)); if (child.EvaluationType.CanNotBeNull()) { if (!forge.IsMustCoerce) { block .AssignArrayElement( "array", Constant(i), Unbox(Ref(refname), childType)); } else { block .AssignArrayElement( "array", Constant(i), forge.Coercer.CoerceCodegen(Ref(refname), childType)); } } else { var ifNotNull = block.IfCondition(NotEqualsNull(Ref(refname))); if (!forge.IsMustCoerce) { ifNotNull .AssignArrayElement( "array", Constant(i), Unbox(Ref(refname), childType)); } else { ifNotNull .AssignArrayElement( "array", Constant(i), forge.Coercer.CoerceCodegen(Ref(refname), child.EvaluationType)); } if (requiresPrimitive) { block.IfCondition( EqualsNull(Ref(refname))) .BlockThrow( NewInstance(typeof(EPException), Constant(PRIMITIVE_ARRAY_NULL_MSG))); } } } block.MethodReturn(Ref("array")); return LocalMethod(methodNode); }