private IAnalysisResult GetResolvedType(Genero4glAst ast, out string errMsg) { errMsg = null; IAnalysisResult result = null; // 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) { errMsg = string.Format("Type {0} not found.", _typeNameString); } else { if (res is GeneroPackageClass || res is TypeDefinitionNode) { result = res; } else { errMsg = string.Format("Invalid type {0} found.", _typeNameString); } } return(result); }
public bool HasChildFunctions(Genero4glAst ast) { if (Children.Count == 1) { var node = Children[Children.Keys[0]]; if (node is ArrayTypeReference) { return(true); } else if (node is RecordDefinitionNode) { return((node as RecordDefinitionNode).HasChildFunctions(ast)); } } else { if (!string.IsNullOrWhiteSpace(_typeNameString)) { if (_typeNameString.Equals("string", StringComparison.OrdinalIgnoreCase)) { return(true); } else { // try to determine if the _typeNameString is a user defined type IAnalysisResult udt = ast.TryGetUserDefinedType(_typeNameString, LocationIndex); if (udt != null) { return(udt.HasChildFunctions(ast)); } // check for package class IGeneroProject dummyProj; IProjectEntry projEntry; bool dummyDef; udt = ast.GetValueByIndex(_typeNameString, LocationIndex, ast._functionProvider, ast._databaseProvider, ast._programFileProvider, false, out dummyDef, out dummyProj, out projEntry); if (udt != null) { return(udt.HasChildFunctions(ast)); } } } } return(false); }
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); } } } } }
public IEnumerable <MemberResult> GetMembers(Genero4glAst ast, MemberType memberType, bool function) { bool dummyDef; List <MemberResult> members = new List <MemberResult>(); if (Children.Count == 1) { // we have an array type or a record type definition var node = Children[Children.Keys[0]]; if (node is ArrayTypeReference) { return((node as ArrayTypeReference).GetMembersInternal(ast, memberType, function)); } else if (node is RecordDefinitionNode) { return((node as RecordDefinitionNode).GetMembers(ast, memberType, function)); } } else { if (!string.IsNullOrWhiteSpace(TableName)) { // TODO: return the table's columns } else if (_typeNameString.Equals("string", StringComparison.OrdinalIgnoreCase)) { return(Genero4glAst.StringFunctions.Values.Select(x => new MemberResult(x.Name, x, GeneroMemberType.Method, ast))); } else if (_typeNameString.Equals("text", StringComparison.OrdinalIgnoreCase)) { return(Genero4glAst.TextFunctions.Values.Select(x => new MemberResult(x.Name, x, GeneroMemberType.Method, ast))); } else if (_typeNameString.Equals("byte", StringComparison.OrdinalIgnoreCase)) { return(Genero4glAst.ByteFunctions.Values.Select(x => new MemberResult(x.Name, x, GeneroMemberType.Method, ast))); } else { // try to determine if the _typeNameString is a user defined type (or package class), in which case we need to call its GetMembers function IAnalysisResult udt = ast.TryGetUserDefinedType(_typeNameString, LocationIndex); if (udt != null) { return(udt.GetMembers(ast, memberType, function)); } foreach (var includedFile in ast.ProjectEntry.GetIncludedFiles()) { if (includedFile.Analysis != null) { IGeneroProject dummyProj; IProjectEntry dummyProjEntry; var res = includedFile.Analysis.GetValueByIndex(_typeNameString, 1, null, null, null, false, out dummyDef, out dummyProj, out dummyProjEntry); if (res != null) { return(res.GetMembers(ast, memberType, function)); } } } if (ast.ProjectEntry.ParentProject.ReferencedProjects.Count > 0) { foreach (var refProj in ast.ProjectEntry.ParentProject.ReferencedProjects.Values) { if (refProj is GeneroProject) { IProjectEntry dummyProj; udt = (refProj as GeneroProject).GetMemberOfType(_typeNameString, ast, false, true, false, false, out dummyProj); if (udt != null) { return(udt.GetMembers(ast, memberType, function)); } } } } // check for package class IGeneroProject dummyProject; IProjectEntry projEntry; udt = ast.GetValueByIndex(_typeNameString, LocationIndex, ast._functionProvider, ast._databaseProvider, ast._programFileProvider, false, out dummyDef, out dummyProject, out projEntry); if (udt != null) { return(udt.GetMembers(ast, memberType, function)); } } } return(members); }
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); }