private void makeOutputTypeInference(ExpressionNode expression, TypeInfo toType, HashMap<TypeInfo, TypeVariableInfo> typeVariables) { if (expression.ExpressionKind == ExpressionKind.Lambda || BytecodeHelper.isDelegateType(toType) || BytecodeHelper.isExpressionTreeType(toType)) { MethodInfo method = getInvokeMethod(toType); if (method == null) { return; } if (expression.ExpressionKind == ExpressionKind.Lambda) { var lambda = (LambdaExpressionNode)expression; if (lambda.Parameters.size() != method.Parameters.count()) { return; } } var paramTypes = new ArrayList<TypeInfo>(); foreach (var p in method.Parameters) { TypeVariableInfo pinfo = typeVariables[p.Type]; if (pinfo != null) { if (pinfo.fixedType != null) { paramTypes.add(pinfo.fixedType); } else { return; } } else { var t = bindGenericParameters(typeVariables, p.Type); if (t == null) { return; } else { paramTypes.add(t); } } } if (expression.ExpressionKind == ExpressionKind.Lambda) { context.CodeValidationContext.pushLambdaParameters(paramTypes); var success = expressionValidator.handleExpressionNoError(expression, null, true); context.CodeValidationContext.popLambdaParameters(); var info = expression.getUserData(typeof(ExpressionInfo)); if (info == null) { return; } expression.removeUserData(typeof(ExpressionInfo)); if (success) { makeLowerBoundInference(context.CodeValidationContext.LambdaReturnType, method.ReturnType, typeVariables); } } else { var info = expression.getUserData(typeof(ExpressionInfo)); if (info == null) { return; } var meth = resolveMethodGroup(info, method, paramTypes); if (meth == null) { makeLowerBoundInference(ValidationHelper.getType(context, expression), toType, typeVariables); } else { makeLowerBoundInference(meth.ReturnType, method.ReturnType, typeVariables); } } } else { var info = expression.getUserData(typeof(ExpressionInfo)); if (info == null) { return; } makeLowerBoundInference(info.Type, toType, typeVariables); } }
private bool isArgumentCompatible(ExpressionNode argNode, TypeInfo paramType) { var ainfo = argNode.getUserData(typeof(ExpressionInfo)); var cleanInfo = false; if (ainfo == null && argNode.ExpressionKind == ExpressionKind.Lambda) { if (!expressionValidator.handleExpressionNoError(argNode, paramType, true)) { argNode.removeUserData(typeof(ExpressionInfo)); return false; } ainfo = argNode.getUserData(typeof(ExpressionInfo)); cleanInfo = true; } if (ainfo == null) { return !paramType.IsPrimitive; } if (BytecodeHelper.isDelegateType(paramType)) { if (!resolveDelegate(paramType, argNode, null, null)) { if (cleanInfo) { argNode.removeUserData(typeof(ExpressionInfo)); } return false; } } else if (ValidationHelper.isMethod(argNode)) { return false; } else if (paramType != ValidationHelper.getType(context, argNode)) { if (!ValidationHelper.isAssignable(context, paramType, argNode)) { if (cleanInfo) { argNode.removeUserData(typeof(ExpressionInfo)); } return false; } } if (cleanInfo) { argNode.removeUserData(typeof(ExpressionInfo)); } return true; }
private void makeExplicitParameterTypeInference(ExpressionNode expression, TypeInfo toType, HashMap<TypeInfo, TypeVariableInfo> typeVariableInfos) { var method = getInvokeMethod(toType); if (method == null) { return; } if (expression.ExpressionKind == ExpressionKind.Lambda) { var lambda = (LambdaExpressionNode)expression; if (lambda.Parameters.size() != method.Parameters.count()) { return; } } var rinfo = typeVariableInfos[method.ReturnType]; if (rinfo != null) { foreach (var p in method.Parameters) { if (p.Type == method.ReturnType) { continue; } var pinfo = typeVariableInfos[p.Type]; if (pinfo != null) { rinfo.dependencies.add(pinfo.genericParameterType); } } } if (expression.ExpressionKind == ExpressionKind.Lambda) { var lambda = (LambdaExpressionNode)expression; var fromTypes = new ArrayList<TypeInfo>(); var pit = method.Parameters.iterator(); foreach (var p in lambda.Parameters) { var ptype = pit.next().Type; if (p.Type == null) { if (ptype.IsClosed) { fromTypes.add(ptype); } else { return; } } else { fromTypes.add(CompilerHelper.resolveTypeReference(context, context.CurrentType.PackageName, p.Type)); } } context.CodeValidationContext.pushLambdaParameters(fromTypes); bool success = expressionValidator.handleExpressionNoError(expression, null, true); context.CodeValidationContext.popLambdaParameters(); var info = expression.getUserData(typeof(ExpressionInfo)); if (info == null) { return; } expression.removeUserData(typeof(ExpressionInfo)); if (!success) { return; } var mit = method.Parameters.iterator(); var fit = fromTypes.iterator(); while (mit.hasNext()) { makeExactInference(fit.next(), mit.next().Type, typeVariableInfos); } makeExactInference(context.CodeValidationContext.LambdaReturnType, method.ReturnType, typeVariableInfos); } else { var info = expression.getUserData(typeof(ExpressionInfo)); if (info == null) { return; } var paramTypes = new ArrayList<TypeInfo>(); foreach (var p in method.Parameters) { paramTypes.add(p.Type); } var meth = resolveMethodGroup(info, method, paramTypes); if (meth == null) { return; } var mit = method.Parameters.iterator(); var cit = meth.Parameters.iterator(); while (mit.hasNext()) { makeExactInference(cit.next().Type, mit.next().Type, typeVariableInfos); } makeExactInference(meth.ReturnType, method.ReturnType, typeVariableInfos); } }
private BetterConversionResult getBetterConversionFromExpression(TypeInfo leftType, TypeInfo rightType, ExpressionNode expression) { if (leftType == rightType) { return BetterConversionResult.Neither; } if (expression.ExpressionKind == ExpressionKind.Lambda) { var leftMethod = getInvokeMethod(leftType); var rightMethod = getInvokeMethod(rightType); var leftReturnType = leftMethod.ReturnType; var rightReturnType = rightMethod.ReturnType; var lit = leftMethod.Parameters.iterator(); var rit = rightMethod.Parameters.iterator(); List<TypeInfo> paramTypes = null; while (lit.hasNext()) { var lt = lit.next().Type; var rt = rit.next().Type; if (lt != rt) { return BetterConversionResult.Neither; } if (paramTypes == null) { paramTypes = new ArrayList<TypeInfo>(); } paramTypes.add(lt); } if (paramTypes != null) { context.CodeValidationContext.pushLambdaParameters(paramTypes); } else { context.CodeValidationContext.pushLambdaParameters(Collections.emptyList<TypeInfo>()); } expressionValidator.handleExpressionNoError(expression, null, true); context.CodeValidationContext.popLambdaParameters(); var info = expression.getUserData(typeof(ExpressionInfo)); expression.removeUserData(typeof(ExpressionInfo)); if (info != null) { if (leftReturnType == context.TypeSystem.VoidType) { return BetterConversionResult.RightIsBetter; } if (rightReturnType == context.TypeSystem.VoidType) { return BetterConversionResult.LeftIsBetter; } return getBetterConversionFromType(leftReturnType, rightReturnType, context.CodeValidationContext.LambdaReturnType); } return BetterConversionResult.Neither; } else { var info = expression.getUserData(typeof(ExpressionInfo)); if (info == null) { return BetterConversionResult.Neither; } return getBetterConversionFromType(leftType, rightType, ValidationHelper.getType(context, expression)); } }