// 1. In some class's scope, classScope != kInvalidIndex; // 1.1 In the same class scope, return member function directly // 1.2 In the derive class scope, return member fucntion != kPrivate // 1.3 Return member function whose access == kPublic // // 2. In global scope, classScope == kInvalidIndex; public ProcedureNode GetMemberFunction(string procName, List <ProtoCore.Type> argTypeList, int classScope, out bool isAccessible, out int functionHostClassIndex, bool isStaticOrConstructor = false) { isAccessible = false; functionHostClassIndex = Constants.kInvalidIndex; if (ProcTable == null) { return(null); } ProcedureMatchOptions opts = new ProcedureMatchOptions() { FunctionName = procName, ParameterTypes = argTypeList, ExcludeAutoGeneratedThisProc = true, ExactMatchWithNumArgs = false, ExactMatchWithArgTypes = false, FilterCallback = x => (!isStaticOrConstructor) || (x.IsConstructor || x.IsStatic) }; int functionIndex = ProcTable.GetFunctionBySignature(opts, out ProcedureNode procNode); if (functionIndex != Constants.kInvalidIndex) { int myClassIndex = TypeSystem.classTable.IndexOf(Name); functionHostClassIndex = myClassIndex; procNode = ProcTable.Procedures[functionIndex]; if (classScope == Constants.kInvalidIndex) { isAccessible = (procNode.AccessModifier == CompilerDefinitions.AccessModifier.Public); } else if (classScope == myClassIndex) { isAccessible = true; } else if (TypeSystem.classTable.ClassNodes[classScope].IsMyBase(myClassIndex)) { isAccessible = (procNode.AccessModifier != CompilerDefinitions.AccessModifier.Private); } else { isAccessible = (procNode.AccessModifier == CompilerDefinitions.AccessModifier.Public); } return(procNode); } if (Base != Constants.kInvalidIndex) { procNode = TypeSystem.classTable.ClassNodes[Base].GetMemberFunction(procName, argTypeList, classScope, out isAccessible, out functionHostClassIndex, isStaticOrConstructor); } return(procNode); }
public int IndexOf(string name, List <ProtoCore.Type> argTypeList, bool isStaticOrConstructor = false) { ProcedureMatchOptions opts = new ProcedureMatchOptions() { FunctionName = name, ParameterTypes = argTypeList, ExcludeAutoGeneratedThisProc = true, ExactMatchWithNumArgs = false, ExactMatchWithArgTypes = false, FilterCallback = x => !isStaticOrConstructor || (x.IsStatic || x.IsConstructor) }; return(GetFunctionBySignature(opts, out ProcedureNode _)); }
/// <summary> /// Get function by its signature. /// </summary> /// <param name="opts">Matching options</param> /// <param name="outputProcNode">Output procedure node. Null if nothing is found</param> /// <returns>Index of the ProcedureNode in the Procedures list. Returns -1 If nothing is found</returns> internal int GetFunctionBySignature(ProcedureMatchOptions opts, out ProcedureNode outputProcNode) { int outputProcNodeIndex = Constants.kInvalidIndex; outputProcNode = null; // how many default parameters are used int smallestDefaultArgNum = int.MaxValue; for (int ii = 0; ii < Procedures.Count; ++ii) { var f = Procedures[ii]; if (opts.FilterCallback(f) == false) { continue; } if ((opts.FunctionName != f.Name) || (opts.ExcludeAutoGeneratedThisProc && f.IsAutoGeneratedThisProc) || (opts.IsStatic != null) && (opts.IsStatic != f.IsStatic) || (opts.IsConstructor != null) && (opts.IsConstructor != f.IsConstructor)) { goto NotMatch; } if (!f.IsActive) { goto NotMatch; } if (opts.ParameterTypes != null) { var argNum = f.ArgumentTypes.Count; var paramNum = opts.ParameterTypes.Count; if (opts.ExactMatchWithNumArgs && (argNum != paramNum)) { goto NotMatch; } if (opts.ExactMatchWithArgTypes) { for (int k = 0; k < paramNum; k++) { if (f.ArgumentTypes[k].Name != opts.ParameterTypes[k].Name || f.ArgumentTypes[k].UID != opts.ParameterTypes[k].UID) { goto NotMatch; } } } int defaultArgs = f.ArgumentInfos.Count(X => X.DefaultExpression != null); if ((argNum < paramNum) || (defaultArgs < argNum - paramNum)) { // The current procedure has either: // too less arguments that we are looking for. // or // too many arguments(even with defaults) than we are looking for goto NotMatch; } // Look for the function with the least amount of default arguments var num = argNum - paramNum; if (num <= smallestDefaultArgNum) { smallestDefaultArgNum = num; outputProcNodeIndex = ii; outputProcNode = Procedures[ii]; } if (smallestDefaultArgNum == 0) { break; } } else { outputProcNodeIndex = ii; outputProcNode = Procedures[ii]; break; } NotMatch: ; } return(outputProcNodeIndex); }