private type_node GetMostCommonType(int kind = 0)
        {
            if (resultExpressionsTypes.Count == 0)
            {
                if (kind == 0)
                {
                    syntaxTreeVisitor.AddError(syntaxTreeVisitor.get_location(lambdaHeader), "IMPOSSIBLE_TO_INFER_RESULT_TYPE_IN_LAMBDA");
                }
                else
                {
                    syntaxTreeVisitor.AddError(syntaxTreeVisitor.get_location(lambdaHeader), "IMPOSSIBLE_TO_INFER_RESULT_TYPE");
                }
            }

            var mostCommonType = resultExpressionsTypes[0].Item1;

            for (var i = 1; i < resultExpressionsTypes.Count; i++)
            {
                if (convertion_data_and_alghoritms.eq_type_nodes(mostCommonType, resultExpressionsTypes[i].Item1))
                {
                    continue;
                }
                var typeComparisonResult = type_table.compare_types(resultExpressionsTypes[i].Item1, mostCommonType);
                if (typeComparisonResult == type_compare.non_comparable_type)
                {
                    syntaxTreeVisitor.AddError(new CanNotConvertTypes(resultExpressionsTypes[i].Item3, resultExpressionsTypes[i].Item1, mostCommonType, syntaxTreeVisitor.get_location(resultExpressionsTypes[i].Item2)));
                }
                if (typeComparisonResult == type_compare.greater_type)
                {
                    mostCommonType = resultExpressionsTypes[i].Item1;
                }
            }

            return(mostCommonType);
        }
        public override void visit(ident id)
        {
            var idName = id.name.ToLower();

            SymbolInfo si = _visitor.context.find_first(idName);

            if (si == null)
            {
                if (InLambdaContext)
                {
                    _visitor.AddError(new ThisTypeOfVariablesCannotBeCaptured(_visitor.get_location(id)));
                    return;
                }
                return;
            }

            if (si.sym_info.semantic_node_type == semantic_node_type.namespace_variable ||
                si.sym_info.semantic_node_type == semantic_node_type.common_namespace_function_node ||
                si.sym_info.semantic_node_type == semantic_node_type.namespace_constant_definition ||
                si.sym_info.semantic_node_type == semantic_node_type.compiled_function_node ||
                si.sym_info.semantic_node_type == semantic_node_type.common_method_node || // SSM bug fix  #167
                si.sym_info.semantic_node_type == semantic_node_type.compiled_namespace_node ||
                si.sym_info.semantic_node_type == semantic_node_type.compiled_variable_definition ||
                si.sym_info.semantic_node_type == semantic_node_type.common_type_node ||
                si.sym_info.semantic_node_type == semantic_node_type.compiled_type_node ||
                si.sym_info.semantic_node_type == semantic_node_type.basic_interface_node ||
                si.sym_info.semantic_node_type == semantic_node_type.common_unit_node ||
                si.sym_info.semantic_node_type == semantic_node_type.compiled_unit_node ||
                si.sym_info.semantic_node_type == semantic_node_type.template_type ||
                si.sym_info.semantic_node_type == semantic_node_type.basic_function_node && idName == "exit")
            {
                return;
            }

            var acceptableVarType = si.sym_info.semantic_node_type == semantic_node_type.local_variable ||
                                    si.sym_info.semantic_node_type == semantic_node_type.local_block_variable ||
                                    si.sym_info.semantic_node_type == semantic_node_type.common_parameter ||
                                    si.sym_info.semantic_node_type == semantic_node_type.class_field
            ;

            if (!(acceptableVarType) && InLambdaContext)
            {
                _visitor.AddError(new ThisTypeOfVariablesCannotBeCaptured(_visitor.get_location(id)));
                return;
            }

            /*if (si.sym_info.semantic_node_type == semantic_node_type.class_field && InLambdaContext)
             * {
             *  var semClassField = (class_field)si.sym_info;
             *  if (semClassField.polymorphic_state != polymorphic_state.ps_common)
             *  {
             *      _visitor.AddError(new ThisTypeOfVariablesCannotBeCaptured(_visitor.get_location(id)));
             *      return;
             *  }
             * }*/

            if (si.scope == null)
            {
                return;
            }

            var scopeIndex      = si.scope.ScopeNum;
            var selfWordInClass = false;

            CapturedVariablesTreeNode scope;

            if (_scopesCapturedVarsNodesDictionary.TryGetValue(scopeIndex, out scope))
            {
                var prScope = scope as CapturedVariablesTreeNodeProcedureScope;
                if (prScope != null && acceptableVarType)
                {
                    if (si.sym_info.semantic_node_type == semantic_node_type.local_variable)
                    {
                        if (!(idName == compiler_string_consts.self_word && si.scope is PascalSharp.Internal.TreeConverter.SymbolTable.ClassMethodScope && _classScope != null) && InLambdaContext)
                        {
                            _visitor.AddError(new ThisTypeOfVariablesCannotBeCaptured(_visitor.get_location(id)));
                        }
                    }
                    if (si.sym_info.semantic_node_type == semantic_node_type.common_parameter && prScope.FunctionNode.parameters.First(v => v.name.ToLower() == idName).parameter_type != parameter_type.value && InLambdaContext)
                    {
                        _visitor.AddError(new CannotCaptureNonValueParameters(_visitor.get_location(id)));
                    }

                    if (idName == compiler_string_consts.self_word && si.scope is PascalSharp.Internal.TreeConverter.SymbolTable.ClassMethodScope &&
                        _classScope != null)
                    {
                        var selfField = _classScope.VariablesDefinedInScope.Find(var => var.SymbolInfo == si);

                        if (selfField == null)
                        {
                            _classScope.VariablesDefinedInScope.Add(
                                new CapturedVariablesTreeNode.CapturedSymbolInfo(null, si));
                        }

                        selfWordInClass = true;
                    }
                    else
                    {
                        var field = prScope.VariablesDefinedInScope.Find(var => var.SymbolInfo == si);

                        if (field == null)
                        {
                            prScope.VariablesDefinedInScope.Add(new CapturedVariablesTreeNode.CapturedSymbolInfo(null,
                                                                                                                 si));
                        }
                    }
                }

                var clScope = scope as CapturedVariablesTreeNodeClassScope;
                if (clScope != null && acceptableVarType)
                {
                    var field = clScope.VariablesDefinedInScope.Find(var => var.SymbolInfo == si);

                    if (field == null)
                    {
                        clScope.VariablesDefinedInScope.Add(new CapturedVariablesTreeNode.CapturedSymbolInfo(null, si));
                    }

                    if (si.access_level != access_level.al_public)
                    {
                        if (!clScope.NonPublicMembersNamesMapping.ContainsKey(idName))
                        {
                            var name          = LambdaHelper.GetNameForNonPublicMember(idName);
                            var semClassField = (class_field)si.sym_info;
                            var pn            = new common_property_node(name, _visitor.context._ctn, null, field_access_level.fal_public, semClassField.polymorphic_state);
                            pn.internal_property_type = _visitor.convert_strong(id).type;
                            clScope.NonPublicMembersNamesMapping.Add(idName, new Tuple <string, class_field, semantic_node>(name, semClassField, pn));
                        }
                    }
                }

                var idRef = (selfWordInClass ? _classScope : scope)
                            .VariablesDefinedInScope
                            .Find(var => var.SymbolInfo == si);

                if (idRef == null)                                     //TODO: Осторожнее переделать
                {
                    {
                        return;
                    }
                }

                if (_currentTreeNode.CorrespondingSyntaxTreeNode != null)
                {
                    var varName  = ((IVAriableDefinitionNode)idRef.SymbolInfo.sym_info).name;                     //TODO: случай параметров и полей класса!!!!!!!!!!!!!!!!!!
                    var substKey = new SubstitutionKey(varName, idRef.SyntaxTreeNodeWithVarDeclaration, _currentTreeNode.CorrespondingSyntaxTreeNode);

                    if (!_identsReferences.ContainsKey(substKey))
                    {
                        _identsReferences.Add(substKey, new List <ident>());
                    }

                    _identsReferences[substKey].Add(id);
                }

                if (InLambdaContext && scope is CapturedVariablesTreeNodeLambdaScope &&
                    scopeIndex < _currentLambdaScopeNodeStack.Peek().ScopeIndex) //TODO: Захват параметров лямбды в другой лямбде
                {
                    _visitor.AddError(new ThisTypeOfVariablesCannotBeCaptured(_visitor.get_location(id)));
                    return;
                }

                if (!InLambdaContext ||
                    scopeIndex >= _currentLambdaScopeNodeStack.Peek().ScopeIndex)
                {
                    return;
                }

                var stackAsList = _currentLambdaScopeNodeStack.ToList();
                stackAsList.RemoveAt(0);

                if (!_currentLambdaScopeNodeStack.Peek().CapturedVarsSymbolInfo.Contains(si))
                {
                    _currentLambdaScopeNodeStack.Peek().CapturedVarsSymbolInfo.Add(si);
                    foreach (var capturedVariablesTreeNodeLambdaScope in stackAsList)
                    {
                        if (!capturedVariablesTreeNodeLambdaScope.CapturedVarsSymbolInfo.Contains(si))
                        {
                            capturedVariablesTreeNodeLambdaScope.CapturedVarsSymbolInfo.Add(si);
                        }
                    }
                }
                if (!idRef.ReferencingLambdas.Contains(_currentLambdaScopeNodeStack.Peek()))
                {
                    idRef.ReferencingLambdas.Add(_currentLambdaScopeNodeStack.Peek());
                    foreach (var capturedVariablesTreeNodeLambdaScope in stackAsList)
                    {
                        if (!idRef.ReferencingLambdas.Contains(capturedVariablesTreeNodeLambdaScope))
                        {
                            idRef.ReferencingLambdas.Add(capturedVariablesTreeNodeLambdaScope);
                        }
                    }
                }
            }
        }
Beispiel #3
0
        public static void Substitute(TreeConversion.syntax_tree_visitor _visitor, declarations decls, statement_list _statementList)
        {
            var tree   = new CapturedVariablesTreeBuilder(_visitor).BuildTree(_statementList);
            var substs = new CapturedVariablesSubstitutionClassGenerator(tree.RootNode).GenerateSubstitutions();

            new CapturedVariablesSubstitutor(tree.IdentsReferences, substs.GeneratedScopeClassesInfo, substs.LambdasToBeAddedAsMethods, substs.SubstitutionsInfo, tree.CapturedVarsNodesDictionary, substs.ConvertingClassNonPublicMembersMapping, _visitor)
            .Substitute(_statementList);

            if (_visitor.context.converting_block() == block_type.function_block && tree.ProcedureScope != null)
            {
                if (decls != null && decls.defs != null)
                {
                    foreach (var def in decls.defs.Where(d => d is const_definition ||
                                                         d is consts_definitions_list ||
                                                         d is variable_definitions))
                    {
                        var constDef = def as const_definition;
                        if (constDef != null)
                        {
                            var finder = new FindMainIdentsVisitor();
                            finder.ProcessNode(constDef.const_value);

                            foreach (var v in finder.vars)
                            {
                                SymbolInfo si = _visitor.context.find_first(v.name);
                                if (si == null)
                                {
                                    continue;
                                }

                                if (tree.ProcedureScope.VariablesDefinedInScope.Any(var => var.SymbolInfo == si))
                                {
                                    _visitor.AddError(new UsingCapturedParameterIsNotAllowedInInitializers(_visitor.get_location(v)));
                                }
                            }
                            continue;
                        }

                        var constDefList = def as consts_definitions_list;
                        if (constDefList != null)
                        {
                            foreach (var cd in constDefList.const_defs)
                            {
                                var finder = new FindMainIdentsVisitor();
                                finder.ProcessNode(cd.const_value);

                                foreach (var v in finder.vars)
                                {
                                    SymbolInfo si = _visitor.context.find_first(v.name);
                                    if (si == null)
                                    {
                                        continue;
                                    }

                                    if (tree.ProcedureScope.VariablesDefinedInScope.Any(var => var.SymbolInfo == si))
                                    {
                                        _visitor.AddError(new UsingCapturedParameterIsNotAllowedInInitializers(_visitor.get_location(v)));
                                    }
                                }
                            }
                            continue;
                        }

                        var varDefList = def as variable_definitions;
                        if (varDefList != null)
                        {
                            foreach (var d in varDefList.var_definitions)
                            {
                                var finder = new FindMainIdentsVisitor();
                                finder.ProcessNode(d.inital_value);

                                foreach (var v in finder.vars)
                                {
                                    SymbolInfo si = _visitor.context.find_first(v.name);
                                    if (si == null)
                                    {
                                        continue;
                                    }

                                    if (tree.ProcedureScope.VariablesDefinedInScope.Any(var => var.SymbolInfo == si))
                                    {
                                        _visitor.AddError(new UsingCapturedParameterIsNotAllowedInInitializers(_visitor.get_location(v)));
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }