protected static void GenerateCodeForArgument(ILGenerator gen, CodeFlow cf, SpelNode argument, TypeDescriptor paramDesc) { cf.EnterCompilationScope(); argument.GenerateCode(gen, cf); var lastDesc = cf.LastDescriptor(); if (lastDesc == null) { throw new InvalidOperationException("No last descriptor"); } var valueTypeOnStack = CodeFlow.IsValueType(lastDesc); // Check if need to box it for the method reference? if (valueTypeOnStack && paramDesc.IsReferenceType) { CodeFlow.InsertBoxIfNecessary(gen, lastDesc); } else if (paramDesc.IsValueType && !paramDesc.IsBoxed && !valueTypeOnStack) { gen.Emit(OpCodes.Unbox_Any, paramDesc.Value); } else { // This would be unnecessary in the case of subtyping (e.g. method takes Number but Integer passed in) CodeFlow.InsertCastClass(gen, paramDesc); } cf.ExitCompilationScope(); }
private void Walk(ILGenerator gen, CodeFlow cf, SpelNode operand) { if (operand is OpPlus plus) { Walk(gen, cf, plus.LeftOperand); Walk(gen, cf, plus.RightOperand); } else if (operand != null) { cf.EnterCompilationScope(); operand.GenerateCode(gen, cf); if (cf.LastDescriptor() != TypeDescriptor.STRING) { gen.Emit(OpCodes.Castclass, typeof(string)); } cf.ExitCompilationScope(); gen.Emit(OpCodes.Callvirt, _appendString); } }