Ejemplo n.º 1
0
 /// <summary>
 /// The default method calls CheckForErrors on all AstNode children of this node.
 /// To do specific error checking, override this method and call the base method at the end.
 /// </summary>
 /// <param name="ast"></param>
 /// <param name="errors"></param>
 public virtual void CheckForErrors(GeneroAst ast, Action <string, int, int> errorFunc,
                                    Dictionary <string, List <int> > deferredFunctionSearches,
                                    FunctionProviderSearchMode searchInFunctionProvider = FunctionProviderSearchMode.NoSearch,
                                    bool isFunctionCallOrDefinition = false)
 {
     foreach (var child in Children)
     {
         child.Value.CheckForErrors(ast, errorFunc, deferredFunctionSearches, searchInFunctionProvider, isFunctionCallOrDefinition);
     }
 }
Ejemplo n.º 2
0
        public override void CheckForErrors(GeneroAst ast, Action <string, int, int> errorFunc,
                                            Dictionary <string, List <int> > deferredFunctionSearches,
                                            FunctionProviderSearchMode searchInFunctionProvider = FunctionProviderSearchMode.NoSearch, bool isFunctionCallOrDefinition = false)
        {
            // check the variable
            if (Variable != null)
            {
                Variable.CheckForErrors(ast, errorFunc, deferredFunctionSearches);
            }

            // check the expression
            base.CheckForErrors(ast, errorFunc, deferredFunctionSearches, searchInFunctionProvider, isFunctionCallOrDefinition);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Evaluates the given expression in at the provided line number and returns the values
        /// that the expression can evaluate to.
        /// </summary>
        /// <param name="exprText">The expression to determine the result of.</param>
        /// <param name="index">The 0-based absolute index into the file where the expression should be evaluated within the module.</param>
        public override IAnalysisResult GetValueByIndex(string exprText, int index, IFunctionInformationProvider functionProvider,
                                                        IDatabaseInformationProvider databaseProvider, IProgramFileProvider programFileProvider,
                                                        bool isFunctionCallOrDefinition, out bool isDeferred,
                                                        out IGeneroProject definingProject, out IProjectEntry projectEntry,
                                                        FunctionProviderSearchMode searchInFunctionProvider = FunctionProviderSearchMode.NoSearch)
        {
            _functionProvider    = functionProvider;
            _databaseProvider    = databaseProvider;
            _programFileProvider = programFileProvider;

            return(GetValueByIndex(exprText, index, this, out definingProject, out projectEntry, out isDeferred,
                                   searchInFunctionProvider,
                                   isFunctionCallOrDefinition));
        }
Ejemplo n.º 4
0
        public override void CheckForErrors(GeneroAst ast, Action <string, int, int> errorFunc,
                                            Dictionary <string, List <int> > deferredFunctionSearches,
                                            FunctionProviderSearchMode searchInFunctionProvider = FunctionProviderSearchMode.NoSearch, bool isFunctionCallOrDefinition = false)
        {
            if (_arguments != null)
            {
                // 1) check to make sure arguments have corresponding defined variables
                foreach (var undefinedArg in _arguments.Where(x => x.Value == null))
                {
                    errorFunc(string.Format("No definition found for parameter {0}", undefinedArg.Key.Token.Value.ToString()),
                              undefinedArg.Key.Span.Start, undefinedArg.Key.Span.End);
                }
            }

            // TODO: 2) Check to make sure the types in return statements match up across multiple return statements.
            if (_internalReturns != null && _internalReturns.Count > 1)
            {
            }

            base.CheckForErrors(ast, errorFunc, deferredFunctionSearches);
        }
Ejemplo n.º 5
0
        public override void CheckForErrors(GeneroAst ast, Action <string, int, int> errorFunc,
                                            Dictionary <string, List <int> > deferredFunctionSearches,
                                            FunctionProviderSearchMode searchInFunctionProvider = FunctionProviderSearchMode.NoSearch, bool isFunctionCallOrDefinition = false)
        {
            // 1) Check to make sure the function call is valid
            if (Function != null)
            {
                Function.CheckForErrors(ast, errorFunc, deferredFunctionSearches);
            }

            // 2) Check the return values
            if (Returns != null)
            {
                foreach (var ret in Returns)
                {
                    ret.CheckForErrors(ast, errorFunc, deferredFunctionSearches);
                    if (ret.ResolvedResult != null &&
                        !(ret.ResolvedResult is VariableDef || ret.ResolvedResult is ProgramRegister))
                    {
                        errorFunc(string.Format("Return item {0} is not a variable", ret.Name), ret.StartIndex, ret.EndIndex);
                    }
                }

                if (Function != null &&
                    Function.Function != null &&
                    Function.Function.ResolvedResult != null &&
                    Function.Function.ResolvedResult is IFunctionResult)
                {
                    var numReturns = (Function.Function.ResolvedResult as IFunctionResult).Returns.Length;
                    if (Returns.Count != numReturns)
                    {
                        errorFunc(string.Format("Unexpected number of return variables ({0}) found, expected {1} variables.", Returns.Count, numReturns), StartIndex, EndIndex);
                    }
                }
            }

            base.CheckForErrors(ast, errorFunc, deferredFunctionSearches);
        }
Ejemplo n.º 6
0
 public abstract IAnalysisResult GetValueByIndex(string exprText, int index, IFunctionInformationProvider functionProvider,
                                                 IDatabaseInformationProvider databaseProvider, IProgramFileProvider programFileProvider,
                                                 bool isFunctionCallOrDefinition, out bool isDeferred,
                                                 out IGeneroProject definingProject, out IProjectEntry projectEntry,
                                                 FunctionProviderSearchMode searchInFunctionProvider = FunctionProviderSearchMode.NoSearch);
Ejemplo n.º 7
0
        public override void CheckForErrors(GeneroAst ast, Action <string, int, int> errorFunc, Dictionary <string, List <int> > deferredFunctionSearches, FunctionProviderSearchMode searchInFunctionProvider = FunctionProviderSearchMode.NoSearch, bool isFunctionCallOrDefinition = false)
        {
            // This will do error checking on the type reference
            base.CheckForErrors(ast, errorFunc, deferredFunctionSearches, searchInFunctionProvider, isFunctionCallOrDefinition);

            if (VariableDefinitions != null)
            {
                if (Children.Count == 1 &&
                    Children[Children.Keys[0]] is TypeReference)
                {
                    var resolvedType = (Children[Children.Keys[0]] as TypeReference).ResolvedType;
                    if (resolvedType != null)
                    {
                        foreach (var vardef in VariableDefinitions)
                        {
                            // apply the resolved type definition to the variable
                            // TODO:
                            //vardef.ResolvedType = resolvedType;
                        }
                    }
                }
            }
        }
Ejemplo n.º 8
0
        public override void CheckForErrors(GeneroAst ast, Action <string, int, int> errorFunc,
                                            Dictionary <string, List <int> > deferredFunctionSearches,
                                            FunctionProviderSearchMode searchInFunctionProvider = FunctionProviderSearchMode.NoSearch,
                                            bool isFunctionCallOrDefinition = false)
        {
            // Check to see if the _firstPiece exists
            IGeneroProject proj;
            IProjectEntry  projEntry;
            string         searchStr = _firstPiece;

            if (searchInFunctionProvider != FunctionProviderSearchMode.NoSearch ||
                isFunctionCallOrDefinition)
            {
                StringBuilder sb = new StringBuilder(searchStr);
                foreach (var child in Children.Values)
                {
                    if (child is ArrayIndexFglNameExpressionPiece)
                    {
                        sb.Append(child.ToString());
                    }
                    else if (child is MemberAccessNameExpressionPiece)
                    {
                        if ((child as MemberAccessNameExpressionPiece).Text != ".*")
                        {
                            sb.Append(child.ToString());
                        }
                        else
                        {
                            break;
                        }
                    }
                }
                searchStr = sb.ToString();
            }

            bool isDeferred;
            // TODO: need to defer database lookups too
            var res = ast.GetValueByIndex(searchStr,
                                          StartIndex,
                                          ast._functionProvider,
                                          ast._databaseProvider,
                                          ast._programFileProvider,
                                          isFunctionCallOrDefinition,
                                          out isDeferred,
                                          out proj,
                                          out projEntry,
                                          searchInFunctionProvider);

            if (res == null)
            {
                if (isDeferred)
                {
                    if (deferredFunctionSearches.ContainsKey(searchStr))
                    {
                        deferredFunctionSearches[searchStr].Add(StartIndex);
                    }
                    else
                    {
                        deferredFunctionSearches.Add(searchStr, new List <int> {
                            StartIndex
                        });
                    }
                }
                else
                {
                    errorFunc(string.Format("No definition found for {0}", searchStr), StartIndex, StartIndex + searchStr.Length);
                }
            }
            else
            {
                if (Name.EndsWith(".*") && res is VariableDef && (res as VariableDef).ResolvedType == null)
                {
                    // need to make sure that the res has a resolved type
                    (res as VariableDef).Type.CheckForErrors(ast, errorFunc, deferredFunctionSearches);
                    (res as VariableDef).ResolvedType = (res as VariableDef).Type.ResolvedType;
                }
                // TODO: need to check array element type
                ResolvedResult = res;
            }

            base.CheckForErrors(ast, errorFunc, deferredFunctionSearches, searchInFunctionProvider, isFunctionCallOrDefinition);
        }
Ejemplo n.º 9
0
        public override void CheckForErrors(GeneroAst ast, Action <string, int, int> errorFunc, Dictionary <string, List <int> > deferredFunctionSearches, FunctionProviderSearchMode searchInFunctionProvider = FunctionProviderSearchMode.NoSearch, bool isFunctionCallOrDefinition = false)
        {
            if (MemberDictionary.Count > 0)
            {
                foreach (var recChild in MemberDictionary.Values)
                {
                    recChild.Type.CheckForErrors(ast, errorFunc, deferredFunctionSearches, searchInFunctionProvider, isFunctionCallOrDefinition);
                }
            }
            else
            {
                // TODO: check the database and table (deferred?)
            }

            // we don't store any children off, so this does nothing
            base.CheckForErrors(ast, errorFunc, deferredFunctionSearches, searchInFunctionProvider, isFunctionCallOrDefinition);
        }
Ejemplo n.º 10
0
        public static IAnalysisResult GetValueByIndex(string exprText, int index, Genero4glAst ast, out IGeneroProject definingProject, out IProjectEntry projectEntry, out bool isDeferredFunction,
                                                      FunctionProviderSearchMode searchInFunctionProvider = FunctionProviderSearchMode.NoSearch, bool isFunctionCallOrDefinition = false,
                                                      bool getTypes = true, bool getVariables = true, bool getConstants = true)
        {
            isDeferredFunction = false;
            definingProject    = null;
            projectEntry       = null;
            //_functionProvider = functionProvider;
            //_databaseProvider = databaseProvider;
            //_programFileProvider = programFileProvider;

            AstNode containingNode = null;

            if (ast != null)
            {
                containingNode = GetContainingNode(ast.Body, index);
                ast.Body.SetNamespace(null);
            }

            IAnalysisResult res = null;
            int             tmpIndex = 0;
            int             bracketDepth = 0;
            bool            doSearch = false;
            bool            resetStartIndex = false;
            int             startIndex = 0, endIndex = 0;
            bool            noEndIndexSet = false;

            if (exprText == null)
            {
                return(null);
            }

            while (tmpIndex < exprText.Length)
            {
                if (resetStartIndex)
                {
                    startIndex      = tmpIndex;
                    resetStartIndex = false;
                    if (startIndex + 1 > exprText.Length)
                    {
                        break;
                    }
                }

                doSearch = false;
                switch (exprText[tmpIndex])
                {
                case '.':
                {
                    if (bracketDepth == 0)
                    {
                        endIndex = tmpIndex - 1;
                        if (endIndex >= startIndex)
                        {
                            // we have our 'piece'
                            doSearch = true;
                        }
                        if (exprText[startIndex] == '.')
                        {
                            startIndex++;
                        }
                    }
                    tmpIndex++;
                }
                break;

                case '[':
                    if (noEndIndexSet)
                    {
                        noEndIndexSet = false;
                    }
                    else
                    {
                        if (bracketDepth == 0)
                        {
                            endIndex = tmpIndex - 1;
                        }
                    }
                    bracketDepth++;
                    tmpIndex++;
                    break;

                case ']':
                {
                    bracketDepth--;
                    if (bracketDepth == 0)
                    {
                        if (exprText.Length <= tmpIndex + 1 ||
                            exprText[tmpIndex + 1] != '[')
                        {
                            // we have our first 'piece'
                            doSearch = true;
                        }
                        else
                        {
                            noEndIndexSet = true;
                        }
                    }
                    tmpIndex++;
                }
                break;

                default:
                {
                    if (bracketDepth == 0 && (tmpIndex + 1 == exprText.Length))
                    {
                        endIndex = tmpIndex;
                        doSearch = true;
                    }
                    tmpIndex++;
                }
                break;
                }

                if (!doSearch)
                {
                    continue;
                }

                // we can do our search
                var dotPiece = exprText.Substring(startIndex, (endIndex - startIndex) + 1);
                if (dotPiece.Contains('('))
                {
                    // remove the params piece
                    int remIndex = dotPiece.IndexOf('(');
                    dotPiece = dotPiece.Substring(0, remIndex);
                }

                bool lookForFunctions = isFunctionCallOrDefinition && (endIndex + 1 == exprText.Length);

                resetStartIndex = true;

                if (res != null)
                {
                    if (ast != null)
                    {
                        var gmi = new GetMemberInput
                        {
                            Name       = dotPiece,
                            AST        = ast,
                            IsFunction = lookForFunctions
                        };
                        IAnalysisResult tempRes = res.GetMember(gmi);
                        if (gmi.DefiningProject != null && definingProject != gmi.DefiningProject)
                        {
                            definingProject = gmi.DefiningProject;
                        }
                        if (gmi.ProjectEntry != null && projectEntry != gmi.ProjectEntry)
                        {
                            projectEntry = gmi.ProjectEntry;
                        }
                        res = tempRes;
                        if (tempRes == null)
                        {
                            res = null;
                            break;
                        }
                    }
                    else
                    {
                        res = null;
                        break;
                    }
                }
                else
                {
                    IFunctionResult funcRes;
                    if (!lookForFunctions)
                    {
                        if (SystemVariables.TryGetValue(dotPiece, out res) ||
                            SystemConstants.TryGetValue(dotPiece, out res) ||
                            SystemMacros.TryGetValue(dotPiece, out res))
                        {
                            continue;
                        }
                    }
                    else
                    {
                        if (SystemFunctions.TryGetValue(dotPiece, out funcRes))
                        {
                            res = funcRes;
                            continue;
                        }

                        if (ast != null && ast._functionProvider != null && ast._functionProvider.Name.Equals(dotPiece, StringComparison.OrdinalIgnoreCase))
                        {
                            res = ast._functionProvider;
                            continue;
                        }
                    }

                    if (containingNode != null && containingNode is IFunctionResult)
                    {
                        IFunctionResult func = containingNode as IFunctionResult;
                        if ((getVariables && func.Variables.TryGetValue(dotPiece, out res)))
                        {
                            continue;
                        }
                        if (!lookForFunctions)
                        {
                            // Check for local vars, types, and constants
                            if ((getTypes && func.Types.TryGetValue(dotPiece, out res)) ||
                                (getConstants && func.Constants.TryGetValue(dotPiece, out res)))
                            {
                                continue;
                            }

                            List <Tuple <IAnalysisResult, IndexSpan> > limitedScopeVars;
                            if ((getVariables && func.LimitedScopeVariables.TryGetValue(dotPiece, out limitedScopeVars)))
                            {
                                foreach (var item in limitedScopeVars)
                                {
                                    if (item.Item2.IsInSpan(index))
                                    {
                                        res = item.Item1;

                                        break;
                                    }
                                }
                                if (res != null)
                                {
                                    continue;
                                }
                            }
                        }
                    }

                    if (ast != null && ast.Body is IModuleResult)
                    {
                        IModuleResult mod = ast.Body as IModuleResult;
                        if (!lookForFunctions)
                        {
                            // check for module vars, types, and constants (and globals defined in this module)
                            if ((getVariables && (mod.Variables.TryGetValue(dotPiece, out res) || mod.GlobalVariables.TryGetValue(dotPiece, out res))) ||
                                (getTypes && (mod.Types.TryGetValue(dotPiece, out res) || mod.GlobalTypes.TryGetValue(dotPiece, out res))) ||
                                (getConstants && (mod.Constants.TryGetValue(dotPiece, out res) || mod.GlobalConstants.TryGetValue(dotPiece, out res))))
                            {
                                continue;
                            }

                            // check for cursors in this module
                            if (mod.Cursors.TryGetValue(dotPiece, out res))
                            {
                                continue;
                            }
                        }
                        else
                        {
                            // check for module functions
                            if (mod.Functions.TryGetValue(dotPiece, out funcRes))
                            {
                                // check for any function info collected at the project entry level, and update the function's documentation with that.
                                if (ast._projEntry != null && ast._projEntry is IGeneroProjectEntry)
                                {
                                    var commentInfo = (ast._projEntry as IGeneroProjectEntry).GetFunctionInfo(funcRes.Name);
                                    if (commentInfo != null)
                                    {
                                        funcRes.SetCommentDocumentation(commentInfo);
                                    }
                                }
                                res = funcRes;
                                continue;
                            }
                        }
                    }

                    // TODO: this could probably be done more efficiently by having each GeneroAst load globals and functions into
                    // dictionaries stored on the IGeneroProject, instead of in each project entry.
                    // However, this does required more upkeep when changes occur. Will look into it...
                    if (ast != null && ast.ProjectEntry != null && ast.ProjectEntry is IGeneroProjectEntry)
                    {
                        IGeneroProjectEntry genProj = ast.ProjectEntry as IGeneroProjectEntry;
                        if (genProj.ParentProject != null &&
                            !genProj.FilePath.ToLower().EndsWith(".inc"))
                        {
                            bool found = false;
                            foreach (var projEntry in genProj.ParentProject.ProjectEntries.Where(x => x.Value != genProj))
                            {
                                if (projEntry.Value.Analysis != null &&
                                    projEntry.Value.Analysis.Body != null)
                                {
                                    projEntry.Value.Analysis.Body.SetNamespace(null);
                                    IModuleResult modRes = projEntry.Value.Analysis.Body as IModuleResult;
                                    if (modRes != null)
                                    {
                                        if (!lookForFunctions)
                                        {
                                            // check global vars, types, and constants
                                            // TODO: need option to enable/disable legacy linking
                                            if ((getVariables && (modRes.Variables.TryGetValue(dotPiece, out res) || modRes.GlobalVariables.TryGetValue(dotPiece, out res))) ||
                                                (getTypes && (modRes.Types.TryGetValue(dotPiece, out res) || modRes.GlobalTypes.TryGetValue(dotPiece, out res))) ||
                                                (getConstants && (modRes.Constants.TryGetValue(dotPiece, out res) || modRes.GlobalConstants.TryGetValue(dotPiece, out res))))
                                            {
                                                found = true;
                                                break;
                                            }

                                            // check for cursors in this module
                                            if (modRes.Cursors.TryGetValue(dotPiece, out res))
                                            {
                                                found = true;
                                                break;
                                            }
                                        }
                                        else
                                        {
                                            // check project functions
                                            if (modRes.Functions.TryGetValue(dotPiece, out funcRes))
                                            {
                                                if (funcRes.AccessModifier == AccessModifier.Public)
                                                {
                                                    res   = funcRes;
                                                    found = true;
                                                    break;
                                                }
                                            }
                                        }
                                    }
                                }
                            }

                            if (found)
                            {
                                continue;
                            }
                        }
                    }

                    // check for classes
                    GeneroPackage package;
                    if (Packages.TryGetValue(dotPiece, out package))
                    {
                        res = package;
                        continue;
                    }

                    /* TODO:
                     * Need to check for:
                     * 1) Temp tables
                     */

                    // Nothing found yet...
                    // If our containing node is at the function or globals level, we need to go deeper
                    if (containingNode != null &&
                        (containingNode is GlobalsNode ||
                         containingNode is FunctionBlockNode ||
                         containingNode is ReportBlockNode))
                    {
                        containingNode = GetContainingNode(containingNode, index);
                    }
                    // check for record field
                    if (containingNode != null &&
                        (containingNode is DefineNode ||
                         containingNode is TypeDefNode))
                    {
                        containingNode = GetContainingNode(containingNode, index);

                        if (containingNode != null &&
                            (containingNode is VariableDefinitionNode ||
                             containingNode is TypeDefinitionNode) &&
                            containingNode.Children.Count == 1 &&
                            containingNode.Children[containingNode.Children.Keys[0]] is TypeReference)
                        {
                            var typeRef = containingNode.Children[containingNode.Children.Keys[0]] as TypeReference;
                            while (typeRef != null &&
                                   typeRef.Children.Count == 1)
                            {
                                if (typeRef.Children[typeRef.Children.Keys[0]] is RecordDefinitionNode)
                                {
                                    var         recNode = typeRef.Children[typeRef.Children.Keys[0]] as RecordDefinitionNode;
                                    VariableDef recField;
                                    if (recNode.MemberDictionary.TryGetValue(exprText, out recField))
                                    {
                                        res = recField;
                                        break;
                                    }
                                    else
                                    {
                                        recField = recNode.MemberDictionary.Where(x => x.Value.LocationIndex < index)
                                                   .OrderByDescending(x => x.Value.LocationIndex)
                                                   .Select(x => x.Value)
                                                   .FirstOrDefault();
                                        if (recField != null)
                                        {
                                            typeRef = recField.Type;
                                        }
                                        else
                                        {
                                            break;
                                        }
                                    }
                                }
                                else if (typeRef.Children[typeRef.Children.Keys[0]] is TypeReference)
                                {
                                    typeRef = typeRef.Children[typeRef.Children.Keys[0]] as TypeReference;
                                }
                                else
                                {
                                    break;
                                }
                            }
                        }
                    }

                    // try an imported module
                    if (ast != null && ast.Body is IModuleResult &&
                        ast.ProjectEntry != null && ast.ProjectEntry != null)
                    {
                        if ((ast.Body as IModuleResult).FglImports.Contains(dotPiece))
                        {
                            // need to get the ast for the other project entry
                            var refProjKVP = (ast.ProjectEntry as IGeneroProjectEntry).ParentProject.ReferencedProjects.Values.FirstOrDefault(
                                x =>
                            {
                                var fn = Path.GetFileNameWithoutExtension(x.Directory);
                                return(fn?.Equals(dotPiece, StringComparison.OrdinalIgnoreCase) ?? false);
                            });
                            if (refProjKVP is IAnalysisResult)
                            {
                                definingProject = refProjKVP;
                                res             = refProjKVP as IAnalysisResult;
                                continue;
                            }

                            IAnalysisResult sysImportMod;
                            // check the system imports
                            if (SystemImportModules.TryGetValue(dotPiece, out sysImportMod))
                            {
                                res = sysImportMod;
                                continue;
                            }
                        }
                    }

                    if (!lookForFunctions)
                    {
                        // try include files
                        var foundInclude = false;
                        if (ast?.ProjectEntry != null)
                        {
                            foreach (var includeFile in ast.ProjectEntry.GetIncludedFiles())
                            {
                                if (includeFile.Analysis?.Body is IModuleResult)
                                {
                                    var mod = includeFile.Analysis.Body as IModuleResult;
                                    if ((getTypes && (mod.Types.TryGetValue(dotPiece, out res) || mod.GlobalTypes.TryGetValue(dotPiece, out res))) ||
                                        (getConstants && (mod.Constants.TryGetValue(dotPiece, out res) || mod.GlobalConstants.TryGetValue(dotPiece, out res))))
                                    {
                                        foundInclude = true;
                                        break;
                                    }
                                }
                            }
                        }
                        if (foundInclude)
                        {
                            continue;
                        }

                        if (ast?._databaseProvider != null)
                        {
                            res = ast._databaseProvider.GetTable(dotPiece);
                            if (res != null)
                            {
                                continue;
                            }
                        }
                    }

                    // Only do a public function search if the dotPiece is the whole text we're searching for
                    // I.e. no namespaces
                    if (lookForFunctions && dotPiece == exprText)
                    {
                        if (searchInFunctionProvider == FunctionProviderSearchMode.Search)
                        {
                            if (res == null && ast?._functionProvider != null)
                            {
                                // check for the function name in the function provider
                                var funcs = ast._functionProvider.GetFunction(dotPiece);
                                if (funcs != null)
                                {
                                    res = funcs.FirstOrDefault();
                                    if (res != null)
                                    {
                                        continue;
                                    }
                                }
                            }
                        }
                        else if (searchInFunctionProvider == FunctionProviderSearchMode.Deferred)
                        {
                            isDeferredFunction = true;
                        }
                    }

                    if (res == null)
                    {
                        break;
                    }
                }
            }

            return(res);
        }
Ejemplo n.º 11
0
 public override void CheckForErrors(GeneroAst ast, Action <string, int, int> errorFunc, Dictionary <string, List <int> > deferredFunctionSearches, FunctionProviderSearchMode searchInFunctionProvider = FunctionProviderSearchMode.NoSearch, bool isFunctionCallOrDefinition = false)
 {
     if (Children.Count > 0)
     {
         base.CheckForErrors(ast, errorFunc, deferredFunctionSearches, searchInFunctionProvider, isFunctionCallOrDefinition);
     }
     else if (!string.IsNullOrWhiteSpace(DatabaseName) ||
              !string.IsNullOrWhiteSpace(TableName) ||
              !string.IsNullOrWhiteSpace(ColumnName))
     {
         // TODO: do deferred checking of these
     }
     else if (_typeNameString != null && !_isConstrainedType)
     {
         // see if the _typeNameString is a base type
         var tok = Tokens.GetToken(_typeNameString);
         if (tok == null || !Genero4glAst.BuiltinTypes.Contains(tok.Kind))
         {
             // if it's not a base type, look up the type
             IGeneroProject dummyProj;
             IProjectEntry  dummyProjEntry;
             bool           isDeferred;
             var            res = Genero4glAst.GetValueByIndex(_typeNameString, StartIndex, ast as Genero4glAst, out dummyProj, out dummyProjEntry, out isDeferred, FunctionProviderSearchMode.NoSearch, false, true, false, false);
             if (res == null)
             {
                 errorFunc(string.Format("Type {0} not found.", _typeNameString), StartIndex, EndIndex);
             }
             else
             {
                 if (res is GeneroPackageClass ||
                     res is TypeDefinitionNode)
                 {
                     ResolvedType = res;
                 }
                 else
                 {
                     errorFunc(string.Format("Invalid type {0} found.", _typeNameString), StartIndex, EndIndex);
                 }
             }
         }
     }
 }
Ejemplo n.º 12
0
 public override void CheckForErrors(GeneroAst ast, Action <string, int, int> errorFunc, Dictionary <string, List <int> > deferredFunctionSearches, FunctionProviderSearchMode searchInFunctionProvider = FunctionProviderSearchMode.NoSearch, bool isFunctionCallOrDefinition = false)
 {
     if (Children.Count > 0)
     {
         base.CheckForErrors(ast, errorFunc, deferredFunctionSearches, searchInFunctionProvider, isFunctionCallOrDefinition);
     }
     else if (!string.IsNullOrWhiteSpace(DatabaseName) ||
              !string.IsNullOrWhiteSpace(TableName) ||
              !string.IsNullOrWhiteSpace(ColumnName))
     {
         // TODO: do deferred checking of these
     }
     else if (_typeNameString != null && !_isConstrainedType)
     {
         // see if the _typeNameString is a base type
         var tok = Tokens.GetToken(_typeNameString);
         if (tok == null || !Genero4glAst.BuiltinTypes.Contains(tok.Kind))
         {
             string resolveErrMsg;
             var    resolvedType = GetResolvedType(ast as Genero4glAst, out resolveErrMsg);
             if (resolvedType == null && resolveErrMsg != null)
             {
                 errorFunc(resolveErrMsg, StartIndex, EndIndex);
             }
             else
             {
                 ResolvedType = resolvedType;
             }
         }
     }
 }
Ejemplo n.º 13
0
        public override void CheckForErrors(GeneroAst ast, Action <string, int, int> errorFunc,
                                            Dictionary <string, List <int> > deferredFunctionSearches,
                                            FunctionProviderSearchMode searchInFunctionProvider = FunctionProviderSearchMode.NoSearch, bool isFunctionCallOrDefinition = false)
        {
            // 1) Check parameters for errors
            //      - undefined identifier
            //      - record without .*
            if (_skipValidationFunctionNames.Contains(Function.Name))
            {
                return;
            }

            // Check for the function name
            if (Function != null)
            {
                Function.CheckForErrors(ast, errorFunc, deferredFunctionSearches, FunctionProviderSearchMode.Deferred, true);
            }

            if (Parameters != null)
            {
                if (Function != null &&
                    Function.ResolvedResult != null &&
                    (Function.ResolvedResult is IFunctionResult))
                {
                    // TODO: if a parameter is a record, then the number of required input arguments increases by the number of fields in that record.
                    int            totalRequiredParams = 0;
                    IGeneroProject proj;
                    IProjectEntry  projEntry;
                    bool           isDeferred;
                    foreach (var param in (Function.ResolvedResult as IFunctionResult).Parameters)
                    {
                        TypeReference typeRef  = null;
                        var           typeName = param.Type;
                        int           index    = typeName.IndexOf("record", StringComparison.OrdinalIgnoreCase);
                        // TODO: need to look into how importable projects populate their parameter result types
                        if (index == 0 && (typeName.Length == 6 || char.IsWhiteSpace(typeName[6])))
                        {
                            if (Function.ResolvedResult is AstNode4gl &&
                                (Function.ResolvedResult as AstNode4gl).StartIndex >= 0)
                            {
                                var useAst = ast as Genero4glAst;
                                if ((Function.ResolvedResult as AstNode4gl).SyntaxTree != null &&
                                    (Function.ResolvedResult as AstNode4gl).SyntaxTree != ast)
                                {
                                    useAst = (Function.ResolvedResult as AstNode4gl).SyntaxTree as Genero4glAst;
                                }
                                // need to retrieve the variable and then get its type
                                var resVar = Genero4glAst.GetValueByIndex(param.Name, (Function.ResolvedResult as AstNode4gl).StartIndex, useAst, out proj, out projEntry, out isDeferred);
                                if (resVar != null &&
                                    resVar is VariableDef)
                                {
                                    typeRef = ((resVar as VariableDef).ResolvedType as TypeReference) ?? (resVar as VariableDef).Type;
                                }
                            }
                        }
                        else
                        {
                            // TODO: eventually, this needs to handle system types
                            var resType = Genero4glAst.GetValueByIndex(typeName, StartIndex, ast as Genero4glAst, out proj, out projEntry, out isDeferred);
                            if (resType != null &&
                                resType is TypeDefinitionNode &&
                                (resType as TypeDefinitionNode).TypeRef != null)
                            {
                                typeRef = (resType as TypeDefinitionNode).TypeRef;
                            }
                        }

                        if (typeRef != null && typeRef.IsRecord && (typeRef.Children[typeRef.Children.Keys[0]] is RecordDefinitionNode))
                        {
                            int recFieldCount = (typeRef.Children[typeRef.Children.Keys[0]] as RecordDefinitionNode).GetMembers(ast as Genero4glAst, Analysis.MemberType.All, false).Count();
                            if (recFieldCount > 0)
                            {
                                totalRequiredParams += recFieldCount;
                            }
                            else
                            {
                                totalRequiredParams++;
                            }
                        }
                        else
                        {
                            totalRequiredParams++;
                        }
                    }

                    int totalParameters = 0;
                    foreach (var param in Parameters)
                    {
                        // The genero compiler does not do error checking of types, so I guess anything goes...
                        // That makes things easier...
                        if (param is FglNameExpression)
                        {
                            var nameParam = param as FglNameExpression;
                            nameParam.CheckForErrors(ast, errorFunc, deferredFunctionSearches, FunctionProviderSearchMode.Deferred);
                            if (nameParam.ResolvedResult != null)
                            {
                                if (nameParam.ResolvedResult is TypeDefinitionNode) // Check for any invalid parameters TODO: others
                                {
                                    errorFunc("Invalid parameter found.", param.StartIndex, param.EndIndex);
                                }
                                else
                                {
                                    TypeReference typeRef = null;
                                    if (nameParam.ResolvedResult is VariableDef)
                                    {
                                        if ((nameParam.ResolvedResult as VariableDef).ResolvedType != null &&
                                            (nameParam.ResolvedResult as VariableDef).ResolvedType is TypeDefinitionNode)
                                        {
                                            var typeDef = (nameParam.ResolvedResult as VariableDef).ResolvedType as TypeDefinitionNode;
                                            if (typeDef?.TypeRef != null)
                                            {
                                                typeRef = typeDef.TypeRef;
                                            }
                                        }
                                        else
                                        {
                                            typeRef = (nameParam.ResolvedResult as VariableDef).Type;
                                        }
                                    }

                                    if (typeRef != null && typeRef.IsRecord && (typeRef.Children[typeRef.Children.Keys[0]] is RecordDefinitionNode))
                                    {
                                        if ((nameParam.ResolvedResult as VariableDef).Type.IsArray)
                                        {
                                            if ((param as FglNameExpression).Name.EndsWith(".*"))
                                            {
                                                // need to get the number of fields in the record, as they count toward our passed parameter total
                                                int recFieldCount = ((RecordDefinitionNode)typeRef.Children[typeRef.Children.Keys[0]]).GetMembers(ast as Genero4glAst, Analysis.MemberType.All, false).Count();
                                                if (recFieldCount > 0)
                                                {
                                                    totalParameters += (recFieldCount - 1); // minus 1 so we can do the increment below
                                                }
                                            }
                                        }
                                        else
                                        {
                                            if (!(param as FglNameExpression).Name.EndsWith(".*") &&
                                                !_allowedNonStarRecordParamFunctions.Contains(Function.Name))
                                            {
                                                errorFunc("Records must be specified with a '.*' ending when passed as a function parameter.", param.StartIndex, param.EndIndex);
                                            }
                                            else
                                            {
                                                if (!_allowedNonStarRecordParamFunctions.Contains(Function.Name))
                                                {
                                                    // need to get the number of fields in the record, as they count toward our passed parameter total
                                                    int recFieldCount = ((RecordDefinitionNode)typeRef.Children[typeRef.Children.Keys[0]]).GetMembers(ast as Genero4glAst, Analysis.MemberType.All, false).Count();
                                                    if (recFieldCount > 0)
                                                    {
                                                        totalParameters += (recFieldCount - 1); // minus 1 so we can do the increment below
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        param.CheckForErrors(ast, errorFunc, deferredFunctionSearches);
                        totalParameters++;
                    }

                    // need to determine if any of the passed in parameters are records, and if so, adjust the passed count
                    if (totalParameters != totalRequiredParams)
                    {
                        errorFunc(string.Format("Unexpected number of parameters ({0}) found, expected {1} variables.", totalParameters, totalRequiredParams), StartIndex, EndIndex);
                    }
                }
            }

            // TODO: should we do something with the anything parameters

            base.CheckForErrors(ast, errorFunc, deferredFunctionSearches);
        }