private void SetupTypedLambdaParameters() { if (m_variableType == null) { throw new NotImplementedException(); } else { if (m_variableType.Type != typeof(VarSpecifiedType)) { if (m_variableType.Type.IsDelegate()) { throw new NotSupportedException("TODO: Parser error"); } m_lambdaDelegateTargetType = m_variableType.Type; } var scope = new ProcedureParsingScope(m_scopeStack.Peek(), "Lambda", ProcedureParsingScope.ScopeType.Lambda); m_scopeStack.Push(scope); foreach (var p in m_lambdaTypedParameters) { scope.AddLambdaExpressionParameter(p.Item1, p.Item2); } } }
private void SetupUntypedLambdaParameters(params string[] parameterNames) { if (m_lambdaLeftExpression.IsMethodReference) { var possibleMethods = m_lambdaLeftExpression.GetMethods().ToArray(); var methods = new List <PrivateMethodInfoForLambdaResolver>(); var instance = m_lambdaLeftExpression.ExpressionCode; // Find methods where this parameter is a delegate that have the right number of parameters. foreach (var method in possibleMethods) { bool matching = false; bool isExtension = method.IsExtension(); var parametersToSkip = (isExtension ? 1 : 0); var parameters = method.GetParameters(); var parTypes = new List <Type>(); if (parameters.Length > parametersToSkip && ImplicitAttribute.IsImplicit(parameters[parametersToSkip])) { parametersToSkip++; // Skip this argument because it is implicit. } var parameterIndex = m_argumentIndex + parametersToSkip; var resolverMethodData = new PrivateMethodInfoForLambdaResolver(method, parameterIndex); if (parameterIndex < parameters.Length) { var parameter = parameters[parameterIndex]; var targetType = parameter.ParameterType; if (targetType.IsDelegate()) { var invokeMethod = targetType.GetMethod("Invoke"); var targetParameters = invokeMethod.GetParameters(); var returnType = invokeMethod.ReturnType; resolverMethodData.DelegateReturnType = returnType; if (parameterNames.Length == targetParameters.Length) { matching = true; if (targetType.HasGenericArguments()) // Only possible if at the same time is an extension method. (!!) { var mga = method.GetGenericArguments().Select(t => new Tuple <string, Type>(t.Name, t)).ToList(); resolverMethodData.MethodGenericArguments = mga; // Resolve those generic arguments from the instance. var typedArgs = instance.Type.GetTypedGenericArguments(parameters[0].ParameterType); foreach (var ti in typedArgs) { var index = mga.FindIndex(t => t.Item1 == ti.Item1); mga[index] = new Tuple <string, Type>(mga[index].Item1, ti.Item2); } // Get types of delegate input parameters. for (int i = 0; i < parameterNames.Length; i++) { var t = targetParameters[i].ParameterType; if (t.IsGenericParameter) { var index = mga.FindIndex(tt => tt.Item1 == t.Name); if (index >= 0) { t = mga[index].Item2; } else { // The type of this input parameter was not found. matching = false; break; } } parTypes.Add(t); } if (matching && returnType.IsGenericParameter) { var nUnknownTypes = mga.Count(tt => tt.Item2.IsGenericParameter); if (nUnknownTypes > 1) { matching = false; } else if (nUnknownTypes == 1) { matching = mga.Exists(tt => tt.Item2 == returnType); } } resolverMethodData.LambdaParameterTypes = parTypes; } else { resolverMethodData.LambdaParameterTypes = parameterNames.Select((n, i) => targetParameters[i].ParameterType).ToList(); resolverMethodData.DelegateType = targetType; } } } } if (matching) { methods.Add(resolverMethodData); } else { m_lambdaLeftExpression.RemoveMethod(method); // Remove the method as a possible match, to avoid further processing. } } if (methods.Count == 1) { var methodData = methods[0]; var method = methodData.Method; var scope = new ProcedureParsingScope(m_scopeStack.Peek(), "Lambda", ProcedureParsingScope.ScopeType.Lambda); m_scopeStack.Push(scope); for (int i = 0; i < parameterNames.Length; i++) { scope.AddLambdaExpressionParameter(methodData.LambdaParameterTypes[i], parameterNames[i]); } m_lambdaDelegateTargetType = methodData.DelegateType; m_lambdaDelegateReturnType = methodData.DelegateReturnType; m_lambdaDelegateGenericArguments = methodData.MethodGenericArguments; } else { throw new NotImplementedException("Having more than one matching methods is not supported. Maybe it never will, and this should just be a parsing error."); } } else { throw new NotImplementedException(); } }