public static int GetSymbolIndex(ClassNode classNode, string name, int classScope, int functionScope, int blockId, List <CodeBlock> codeblocks, out bool hasThisSymbol, out ProtoCore.DSASM.AddressType addressType) { var dict = new SortedDictionary <int, CodeBlock>(); codeblocks.ForEach(x => dict.Add(x.codeBlockId, x)); return(GetSymbolIndex(classNode, name, classScope, functionScope, blockId, dict, out hasThisSymbol, out addressType)); }
// classScope is a global context, it tells we are in which class's scope // functionScope is telling us which function we are in. // // 1. Try to find if the target is a member function's local variable // classScope != kInvalidIndex && functionScope != kInvalidIndex; // // 2. Try to find if the target is a member variable // 2.1 In a member functions classScope != kInvalidIndex && functionScope != kInvalidIndex. // Returns member in derived class, or non-private member in base classes // // 2.2 In a global functions classScope == kInvalidIndex && functionScope != kInvalidIndex. // Returns public member in derived class, or public member in base classes // // 2.3 Otherwise, classScope == kInvalidIndex && functionScope == kInvalidIndex // Return public member in derived class, or public member in base classes internal static int GetSymbolIndex(ClassNode classNode, string name, int classScope, int functionScope, int blockId, SortedDictionary <int, CodeBlock> codeblocks, out bool hasThisSymbol, out ProtoCore.DSASM.AddressType addressType) { hasThisSymbol = false; addressType = ProtoCore.DSASM.AddressType.Invalid; if (classNode.Symbols == null) { return(ProtoCore.DSASM.Constants.kInvalidIndex); } IEnumerable <SymbolNode> allSymbols = classNode.Symbols.GetNodeForName(name); if (allSymbols == null) { return(ProtoCore.DSASM.Constants.kInvalidIndex); } int myself = classNode.TypeSystem.classTable.IndexOf(classNode.Name); bool isInMemberFunctionContext = (classScope == myself) && (functionScope != ProtoCore.DSASM.Constants.kInvalidIndex); bool isInStaticFunction = isInMemberFunctionContext && classNode.ProcTable.Procedures.Count > functionScope && classNode.ProcTable.Procedures[functionScope].IsStatic; // Try for member function variables var blocks = GetAncestorBlockIdsOfBlock(blockId, codeblocks); blocks.Insert(0, blockId); Dictionary <int, SymbolNode> symbolOfBlockScope = new Dictionary <int, SymbolNode>(); foreach (var memvar in allSymbols) { if ((isInMemberFunctionContext) && (memvar.functionIndex == functionScope)) { symbolOfBlockScope[memvar.codeBlockId] = memvar; } } if (symbolOfBlockScope.Count > 0) { foreach (var blockid in blocks) { if (symbolOfBlockScope.ContainsKey(blockid)) { hasThisSymbol = true; addressType = AddressType.VarIndex; return(symbolOfBlockScope[blockid].symbolTableIndex); } } } // Try for member variables. var candidates = new List <SymbolNode>(); foreach (var memvar in allSymbols) { if (memvar.functionIndex == ProtoCore.DSASM.Constants.kGlobalScope) { candidates.Add(memvar); } } // Sort candidates descending based on their class scopes so that // we can search member variable in reverse order of hierarchy tree. candidates.Sort((lhs, rhs) => rhs.classScope.CompareTo(lhs.classScope)); hasThisSymbol = candidates.Count > 0; foreach (var symbol in candidates) { bool isAccessible = false; if (isInMemberFunctionContext) { isAccessible = (symbol.classScope == myself) || (symbol.access != ProtoCore.CompilerDefinitions.AccessModifier.Private); if (isInStaticFunction) { isAccessible = isAccessible && symbol.isStatic; } } else { isAccessible = symbol.access == ProtoCore.CompilerDefinitions.AccessModifier.Public; } if (isAccessible) { addressType = symbol.isStatic ? AddressType.StaticMemVarIndex : AddressType.MemVarIndex; return(symbol.symbolTableIndex); } } return(Constants.kInvalidIndex); }