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);
                }
            }
        }
 public override void EnterBlock([NotNull] SBP.BlockContext context)
 {
     if (m_scopeStack.Count > 0)
     {
         m_scopeStack.Push(new ProcedureParsingScope(m_scopeStack.Peek(), "Block", ProcedureParsingScope.ScopeType.Block));
     }
     else
     {
         m_procedureBaseScope = new ProcedureParsingScope(null, "Procedure", ProcedureParsingScope.ScopeType.Procedure);
         m_scopeStack.Push(m_procedureBaseScope);
     }
     m_expressionData.PushStackLevel("Block");   // "Livrem og seler"
 }
Пример #3
0
 public void AddSubStatement(ProcedureParsingScope statementCode)
 {
     m_subStatements.Add(statementCode);
 }
        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();
            }
        }
 public override void EnterProcedureBody([NotNull] SBP.ProcedureBodyContext context)
 {
     m_scopeStack.Clear();
     m_procedureBaseScope = null;
     m_inFunctionScope    = true;
 }