pascalabcnet/TreeConverter/SymbolTable/DSST/SymbolTable.cs
miks1965 2806f02333 Переделана на стандартную HashTable в таблице символов.
Скорость не упала!
Сделаны ToString для некоторых классов для отображения символов в таблице символов
2017-10-07 14:01:51 +03:00

1220 lines
47 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Copyright (c) Ivan Bondarev, Stanislav Mihalkovich (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Linq;
using PascalABCCompiler.TreeConverter;
using System.Collections.Generic;
using SymbolTable;
using System.Reflection;
namespace PascalABCCompiler.TreeRealization
{
public abstract class BasePCUReader
{
public abstract definition_node CreateInterfaceMember(int offset, string name);
public static void RestoreSymbolsInterfaceMember(SymbolInfoList si, string name)
{
if (si != null)
{
foreach (var si_unit in si.InfoUnitList)
{
if (si_unit.sym_info != null)
if (si_unit.sym_info.semantic_node_type == PascalABCCompiler.TreeRealization.semantic_node_type.wrap_def)
{
PascalABCCompiler.TreeRealization.wrapped_definition_node wdn = (PascalABCCompiler.TreeRealization.wrapped_definition_node)si_unit.sym_info;
si_unit.sym_info = wdn.PCUReader.CreateInterfaceMember(wdn.offset, name);
}
}
}
}
public abstract definition_node CreateInterfaceInClassMember(int offset, string name);
public abstract definition_node CreateImplementationMember(int offset, bool restore_code=true);
public abstract definition_node CreateTypeSynonim(int offset, string name);
public static void RestoreSymbols(SymbolInfoList si, string name, int index = 0)
{
if (si != null)
{
for (int i = index; i < si.InfoUnitList.Count; ++i)
{
if (si.InfoUnitList[i].sym_info != null)
if (si.InfoUnitList[i].sym_info.semantic_node_type == PascalABCCompiler.TreeRealization.semantic_node_type.wrap_def)
{
PascalABCCompiler.TreeRealization.wrapped_definition_node wdn = (PascalABCCompiler.TreeRealization.wrapped_definition_node)si.InfoUnitList[i].sym_info;
RestoreSymbols(si.InfoUnitList[i], wdn, name);
}
}
}
}
static void RestoreSymbols(SymbolInfoUnit si, PascalABCCompiler.TreeRealization.wrapped_definition_node wdn, string name)
{
if (wdn.is_synonim)
si.sym_info = wdn.PCUReader.CreateTypeSynonim(wdn.offset, name);
else
if (si.scope is ClassScope)
si.sym_info = wdn.PCUReader.CreateInterfaceInClassMember(wdn.offset, name);
else
si.sym_info = wdn.PCUReader.CreateImplementationMember(wdn.offset, false);
}
}
/*public class PCUReturner
{
private static Hashtable ht = new Hashtable();
public static void Clear()
{
ht.Clear();
}
public static BasePCUReader GetPCUReader(PascalABCCompiler.TreeRealization.wrapped_definition_node wdn)
{
return (BasePCUReader)ht[wdn];
}
public static void AddPCUReader(PascalABCCompiler.TreeRealization.wrapped_definition_node wdn, BasePCUReader pr)
{
ht[wdn] = pr;
}
}*/
public class wrapped_definition_node : definition_node
{
public int offset;
public bool is_synonim;
public BasePCUReader PCUReader;
public wrapped_definition_node(int offset, BasePCUReader PCUReader)
{
this.offset = offset;
this.PCUReader = PCUReader;
}
public override general_node_type general_node_type
{
get
{
return general_node_type.unit_node;
}
}
public override semantic_node_type semantic_node_type
{
get
{
return semantic_node_type.wrap_def;
}
}
}
}
namespace SymbolTable
{
#region SymbolTableConstants набор констант определяющих поведение таблицы символов
public class SymbolTableConstants
{
//стартовый размер списка областей видимости
public const int AreaList_StartSize=8;
//во сколько раз расширять список областей видимости
public const int AreaList_ResizeParam=2;
//стартовый размер списка информаций о символах
public const int InfoList_StartSize=1;
//рекомендуемый стартовый размер хештаблицы
public const int HashTable_StartSize=8192;
//параметры поведения хеш таблицы
public const int HashTable_StartResise=85; //Расширить хеш на ProcResize процентов,
public const int HashTable_ProcResize =100;//если он заполнен на StartResize процентов
public const int SymbolNotFound=-1;
}
#endregion
#region Scope,DotNETScope,UnitPartScope,UnitInterfaceScope,UnitImplementationScope,ClassScope элемены таблицы областей видимости
//элемент таблицы областей видимости
//при создании добавляет себя в vSymbolTable
public class Scope:BaseScope
{
private string ScopeName()
{
var s = this.GetType().Name;
if (s == "UnitInterfaceScope")
return "GLOBAL";
return s;
}
public override string ToString() => ScopeNum + "->" + TopScopeNum + " ," + ScopeName();
public DSSymbolTable SymbolTable;
public bool CaseSensitive;
public int TopScopeNum;
public bool AddStatementsToFront = false; // SSM - введено для необходимости добавлять statements не только в конец statement_list, но и в начало. Нужно для синтаксически сахарных конструкций: например, для создания объекта класса при замыканиях
public Scope TopScope
{
get
{
if(TopScopeNum>=0)
return SymbolTable.ScopeTable[TopScopeNum];
else
return null;
}
}
//public Scope()
//{
//}
public int ScopeNum;
public Scope(DSSymbolTable vSymbolTable, Scope TopScope)
{
SymbolTable=vSymbolTable;
TopScopeNum=-1;
if (TopScope!=null)
TopScopeNum=TopScope.ScopeNum;
ScopeNum = SymbolTable.ScopeTable.Count;
SymbolTable.ScopeTable.Add(this);
this.CaseSensitive = SemanticRules.SymbolTableCaseSensitive;
}
public Scope(DSSymbolTable vSymbolTable, Scope TopScope, bool CaseSensetive)
{
SymbolTable = vSymbolTable;
TopScopeNum = -1;
if (TopScope != null)
TopScopeNum = TopScope.ScopeNum;
ScopeNum = SymbolTable.ScopeTable.Count;
SymbolTable.ScopeTable.Add(this);
this.CaseSensitive = CaseSensetive;
}
public virtual SymbolInfoList Find(string name)
{
return Find(name, null);
}
public virtual SymbolInfoList Find(string name, Scope CurrentScope)
{
SymbolInfoList si = SymbolTable.Find(this, name, CurrentScope);
if (si == null) return si;
PascalABCCompiler.TreeRealization.BasePCUReader.RestoreSymbols(si, name);
return si;
}
public virtual SymbolInfoList FindOnlyInScopeAndBlocks(string name)
{
return SymbolTable.FindOnlyInScope(this, name, true);
}
public virtual SymbolInfoList FindOnlyInScope(string name)
{
return SymbolTable.FindOnlyInScope(this, name, false);
}
public virtual SymbolInfoList FindOnlyInType(string name, Scope CurrentScope)
{
SymbolInfoList si = SymbolTable.FindOnlyInType(this, name, CurrentScope);
if (si == null) return si;
PascalABCCompiler.TreeRealization.BasePCUReader.RestoreSymbols(si, name);
return si;
}
public void AddSymbol(string Name,SymbolInfoUnit Inf)
{
SymbolTable.Add(this,Name,Inf);
}
}
public class BlockScope : Scope
{
public BlockScope(DSSymbolTable vSymbolTable, Scope TopScope)
: base(vSymbolTable, TopScope)
{
}
}
public class LambdaScope : Scope //lroman//
{
public LambdaScope(DSSymbolTable vSymbolTable, Scope TopScope)
: base(vSymbolTable, TopScope)
{
}
}
public class WithScope : BlockScope
{
public Scope[] WithScopes;
public WithScope(DSSymbolTable vSymbolTable, Scope TopScope, Scope[] WithScopes)
: base(vSymbolTable, TopScope)
{
this.WithScopes = WithScopes;
}
}
public class DotNETScope:Scope
{
public NamespaceScope AdditionalNamespaceScope;
public DotNETScope(DSSymbolTable vSymbolTable):base(vSymbolTable,null,false)
{
}
}
public class UnitPartScope:Scope
{
public Scope[] TopScopeArray;
public UnitPartScope(DSSymbolTable vSymbolTable,Scope TopScope,Scope[] vTopScopeArray):
base(vSymbolTable,TopScope)
{
TopScopeArray=vTopScopeArray;
}
}
public class UnitInterfaceScope:UnitPartScope
{
public UnitInterfaceScope(DSSymbolTable vSymbolTable,Scope TopScope,Scope[] vTopScopeArray):
base(vSymbolTable,TopScope,vTopScopeArray)
{
}
}
public class UnitImplementationScope:UnitPartScope
{
public UnitImplementationScope(DSSymbolTable vSymbolTable, Scope TopScope, Scope[] vTopScopeArray)
:
base(vSymbolTable,TopScope,vTopScopeArray)
{}
}
public class NamespaceScope: UnitInterfaceScope
{
public NamespaceScope(DSSymbolTable vSymbolTable, Scope TopScope, Scope[] vTopScopeArray):
base(vSymbolTable,TopScope,vTopScopeArray)
{
}
}
public class ClassScope:Scope
{
public int BaseClassScopeNum;
public ClassScope PartialScope;
public Scope BaseClassScope
{
get
{
if (BaseClassScopeNum>=0)
return SymbolTable.ScopeTable[BaseClassScopeNum];
else
return null;
}
//TODO: Kolya add this set accessor
//Ask for Alexander
set
{
if (value == null)
{
BaseClassScopeNum = -2;
return;
}
BaseClassScopeNum=value.ScopeNum;
}
}
public ClassScope(DSSymbolTable vSymbolTable,Scope TopScope,Scope BaseClassScope):
base(vSymbolTable,TopScope)
{
BaseClassScopeNum=-2;
if (BaseClassScope!=null)
BaseClassScopeNum=BaseClassScope.ScopeNum;
}
public override SymbolInfoList Find(string name, Scope CurrentScope)
{
SymbolInfoList si_list = SymbolTable.Find(this, name, CurrentScope);
if (PartialScope != null)
{
if (si_list == null)
si_list = SymbolTable.Find(PartialScope, name, CurrentScope);
else
{
si_list.Add(SymbolTable.Find(PartialScope, name, CurrentScope));
}
}
if (si_list == null) return si_list;
PascalABCCompiler.TreeRealization.BasePCUReader.RestoreSymbols(si_list, name);
return si_list;
}
public override SymbolInfoList FindOnlyInType(string name, Scope CurrentScope)
{
SymbolInfoList si = SymbolTable.FindOnlyInType(this, name, CurrentScope);
if (PartialScope != null)
{
if (si == null)
si = SymbolTable.FindOnlyInType(PartialScope, name, CurrentScope);
else
{
si.Add(SymbolTable.FindOnlyInType(PartialScope, name, CurrentScope));
}
}
if (si == null) return si;
PascalABCCompiler.TreeRealization.BasePCUReader.RestoreSymbols(si, name);
return si;
}
}
/*public class GenericTypeInstanceScope : ClassScope
{
private PascalABCCompiler.TreeRealization.generic_instance_type_node _instance_type;
private Scope _orig_scope;
public GenericTypeInstanceScope(PascalABCCompiler.TreeRealization.generic_instance_type_node instance_type,
Scope orig_scope, Scope BaseClassScope)
: base(orig_scope.SymbolTable, orig_scope.TopScope, BaseClassScope)
{
_orig_scope = orig_scope;
_instance_type = instance_type;
}
public override SymbolInfo Find(string name)
{
return _instance_type.ConvertSymbolInfo(_orig_scope.Find(name));
}
public override SymbolInfo Find(string name, Scope CurrentScope)
{
return _instance_type.ConvertSymbolInfo(_orig_scope.Find(name, CurrentScope));
}
public override SymbolInfo FindOnlyInScope(string name)
{
return _instance_type.ConvertSymbolInfo(_orig_scope.FindOnlyInScope(name));
}
public override SymbolInfo FindOnlyInScopeAndBlocks(string name)
{
return _instance_type.ConvertSymbolInfo(_orig_scope.FindOnlyInScopeAndBlocks(name));
}
}*/
//(ssyy) Интерфейс для интерфейсов
public interface IInterfaceScope
{
Scope[] TopInterfaceScopeArray
{
get;
set;
}
}
//ssyy owns
//Область видимости для интерфейсов
//Наследование от ClassScope сделано для простоты, так как в кодах
//местами есть проверки (scope is ClassScope)
public class InterfaceScope : ClassScope, IInterfaceScope
{
private Scope[] _TopInterfaceScopeArray;
public virtual Scope[] TopInterfaceScopeArray
{
get
{
return _TopInterfaceScopeArray;
}
set
{
_TopInterfaceScopeArray = value;
}
}
public InterfaceScope(DSSymbolTable vSymbolTable, Scope TopScope, Scope[] vTopInterfaceScopeArray)
:
base(vSymbolTable, TopScope, null)
{
_TopInterfaceScopeArray = vTopInterfaceScopeArray;
}
public InterfaceScope(DSSymbolTable vSymbolTable, Scope TopScope, Scope BaseClassScope, Scope[] vTopInterfaceScopeArray)
:
base(vSymbolTable, TopScope, BaseClassScope)
{
_TopInterfaceScopeArray = vTopInterfaceScopeArray;
}
}
//\ssyy owns
public class ClassMethodScope:Scope
{
public int MyClassNum;
public Scope MyClass
{
get
{
if (MyClassNum>=0)
return SymbolTable.ScopeTable[MyClassNum];
else
return null;
}
}
public ClassMethodScope(DSSymbolTable vSymbolTable,Scope TopScope,Scope MyClass):
base(vSymbolTable,TopScope)
{
MyClassNum=-2;
if (MyClass!=null)
MyClassNum=MyClass.ScopeNum;
}
}
#endregion
#region AreaListNode элемент списка областей видимости
public class AreaListNode
{
public override string ToString() => InfoList.JoinIntoString();
public int Area;
public List<SymbolInfoUnit> InfoList;//для перегузки
public AreaListNode()
{
InfoList = new List<SymbolInfoUnit>(SymbolTableConstants.InfoList_StartSize);
}
public AreaListNode(int ar,SymbolInfoUnit inf)
{
InfoList = new List<SymbolInfoUnit>(SymbolTableConstants.InfoList_StartSize);
Area=ar;
InfoList.Add(inf);
}
}
#endregion
#region HashTableNode элемент хеш-таблицы
public class HashTableNode
{
public string Name;
public AreaNodesList NumAreaList;
public HashTableNode(string name)
{
Name=name;
NumAreaList=new AreaNodesList(SymbolTableConstants.AreaList_StartSize);
}
public override string ToString()
{
return NumAreaList.ToString();
}
}
#endregion
// Определения
// ОВ - область видимости
// ООВ - особая область видимости в стиле delphi.это:
// - ОВ поцедуры
// - OВ класса + ОВ предков
// - ОВ модуля + ОВ интерфейсных частей всех модулей подклюценных к нему
public class DSSymbolTable
{
public List<Scope> ScopeTable;
public DSHashTable HashTable;
internal bool CaseSensitive;
private Scope LastScope;
//private SymbolInfo FirstInfo;
private Scope CurrentScope;
#region DSSymbolTable(int hash_size,bool case_sensitive)
public DSSymbolTable(int hash_size,bool case_sensitive)
{
CaseSensitive=case_sensitive;
HashTable=new DSHashTable(hash_size);
Clear();
}
#endregion
#region Clear() очистка таблицы
public void Clear()
{
ScopeTable=new List<Scope>();
HashTable.ClearTable();
}
#endregion
#region CreateScope для различных Scope
public LambdaScope CreateLambdaScope(Scope TopScope) //lroman//
{
return new LambdaScope(this, TopScope);
}
public Scope CreateScope(Scope TopScope)
{
return new Scope(this,TopScope);
}
public ClassScope CreateClassScope(Scope TopScope,Scope BaseClass)
{
return new ClassScope(this, TopScope, BaseClass);
}
//ssyy
public InterfaceScope CreateInterfaceScope(Scope TopScope, Scope[] TopInterfaces)
{
return new InterfaceScope(this, TopScope, TopInterfaces);
}
public InterfaceScope CreateInterfaceScope(Scope TopScope, Scope BaseClass, Scope[] TopInterfaces)
{
return new InterfaceScope(this, TopScope, BaseClass, TopInterfaces);
}
public ClassScope CreateInterfaceOrClassScope(bool is_interface)
{
if (is_interface)
{
return CreateInterfaceScope(null, null);
}
else
{
return CreateClassScope(null, null);
}
}
//\ssyy
public UnitInterfaceScope CreateUnitInterfaceScope(Scope[] UsedUnits)
{
return new UnitInterfaceScope(this,null,UsedUnits);
}
public NamespaceScope CreateNamespaceScope(Scope[] UsedUnits, Scope TopScope)
{
return new NamespaceScope(this, TopScope, UsedUnits);
}
public UnitImplementationScope CreateUnitImplementationScope(Scope InterfaceScope,Scope[] UsedUnits)
{
return new UnitImplementationScope(this,InterfaceScope,UsedUnits);
}
public ClassMethodScope CreateClassMethodScope(Scope TopScope,Scope MyClass)
{
return new ClassMethodScope(this,TopScope,MyClass);
}
#endregion
//возвращает номер верхней области видимости относительно
//области Scope
public Scope GetTopScope(Scope scope)
{
//DEBUG
#if (DEBUG)
if ((scope.TopScopeNum>=ScopeTable.Count)|(scope.TopScopeNum<0)) throw new Exception("Ошибка при взятии верхней области видимости: область с номером "+scope.ScopeNum+" не существует");
#endif
return ScopeTable[scope.TopScopeNum];
}
public int GetTopScopeNum(int scope)
{
//DEBUG
#if (DEBUG)
if ((scope>=ScopeTable.Count)|(scope<0)) throw new Exception("Ошибка при взятии верхней области видимости: область с номером "+scope+" не существует");
#endif
return ScopeTable[scope].TopScopeNum;
}
//Возвращает количество уровней на которые надо поднятся начиная с Down чтобы очутиться в Up
//Работает только для процедур. Модуль считает за одно Scope
public int GetRelativeScopeDepth(Scope Up,Scope Down)
{
if (Up==Down) return 0;
int depth=0;
while(Down.TopScopeNum>=0)
{
if (Up==Down) return depth;
if(!(Down is UnitImplementationScope))
depth++;
Down=Down.TopScope;
}
//throw new Exception("Can not execute st depth");
return -1;
}
//Добавление символа
//если такой символ в пр-ве имен уже существует то symbol_info добавляется к AreaListNode[].InfoList[]
public void Add(Scope InScope, string Name, SymbolInfoUnit Inf)
{
//int.try
//{
Inf.scope = InScope;
if (!InScope.CaseSensitive) Name = Name.ToLower();
var hn = HashTable.Add(Name);//ЗДЕСь ВОЗНИКАЕТ НЕДЕТЕРМЕНИРОВАНЯ ОШИБКА - SSM 07.10.17 - странный комментарий. Вроде всё нормально.
// SSM 07.10.17 - переделал внутреннее представление HashTable на основе Dictionary
hn.NumAreaList.Add(new AreaListNode(InScope.ScopeNum, Inf));
//}
// catch (Exception e)
//{
// throw e;
// }
}
//Этот метод ищет ТОЛЬКО В УКАЗАННОЙ ОВ, и не смотрит есть ли имя выше.
//Если это ОВ типа UnitImplementationScope то имя ищется также и
//в верней ОВ, которая типа UnitInterfaceScope
public SymbolInfoList FindOnlyInScope(Scope scope, string Name, bool FindInUpperBlocks)
{
if (!scope.CaseSensitive) Name = Name.ToLower();
CurrentScope = null;
LastScope = null;
SymbolInfoList FirstInfo = new SymbolInfoList();
int Area = scope.ScopeNum;
var tn = HashTable.Find(Name); //найдем имя в хеше
if (tn == null || scope is DotNETScope)//если нет такого ищем в областях .NET
{
Scope an;
an = ScopeTable[Area];
if (an is DotNETScope)
{
AddToSymbolInfo(FirstInfo, (DotNETScope)an, Name);
}
return FirstInfo.InfoUnitList.Count > 0 ? FirstInfo : null;
}
AreaNodesList AreaList = tn.NumAreaList;
int CurrentArea = Area, ai, bs;
do
{
if (ScopeTable[CurrentArea] is UnitPartScope) //мы очутились в модуле
{
//мы в ImplementationPart?
if (ScopeTable[CurrentArea] is UnitImplementationScope)
{
ai = AreaList.IndexOf(CurrentArea);
if (ai >= 0) //что-то нашли!
{
AddToSymbolInfo(AreaList[ai].InfoList, ScopeTable[CurrentArea], FirstInfo);
}
CurrentArea = GetTopScopeNum(CurrentArea);
}
//сейча мы в InterfacePart
ai = AreaList.IndexOf(CurrentArea);
if (ai >= 0) //что-то нашли!
{
AddToSymbolInfo(AreaList[ai].InfoList, ScopeTable[CurrentArea], FirstInfo);
}
if (FirstInfo.InfoUnitList.Count > 0)
return FirstInfo;
}
if (ScopeTable[CurrentArea] is WithScope)//мы очутились в Width
{
ai = AreaList.IndexOf(CurrentArea);
if (ai >= 0) //что-то нашли!
{
AddToSymbolInfo(AreaList[ai].InfoList, ScopeTable[CurrentArea], FirstInfo);
}
if (FirstInfo.InfoUnitList.Count > 0) //если что-то нашли то заканчиваем
return FirstInfo;
FindAllInAreaList(Name, (ScopeTable[CurrentArea] as WithScope).WithScopes, AreaList, true, FirstInfo);
if (FirstInfo.InfoUnitList.Count > 0) //если что-то нашли то заканчиваем
return FirstInfo;
}
else
{
ai = AreaList.IndexOf(CurrentArea);
if (ai >= 0) //что-то нашли!
{
AddToSymbolInfo(AreaList[ai].InfoList, ScopeTable[CurrentArea], FirstInfo);
return FirstInfo.InfoUnitList.Count > 0 ? FirstInfo : null;
}
}
bs = CurrentArea;
CurrentArea = GetTopScopeNum(CurrentArea);
} while (CurrentArea >= 0 && (FindInUpperBlocks && ScopeTable[bs] is BlockScope));
return null;
}
private void FindAllInClass(string name, int ClassArea, AreaNodesList AreaList, bool OnlyInThisClass, SymbolInfoList FirstInfo)
{
int ai;
Scope ar = ScopeTable[ClassArea];
if ((ai = AreaList.IndexOf(ClassArea)) >= 0)
AddToSymbolInfo(AreaList[ai].InfoList, ar, FirstInfo);
if (ar is DotNETScope)
{
PascalABCCompiler.TreeRealization.BasePCUReader.RestoreSymbols(FirstInfo, name);
AddToSymbolInfo(FirstInfo, (DotNETScope)ar, name);
return;
}
ClassScope cl = (ClassScope)ScopeTable[ClassArea];
if (!OnlyInThisClass)
while (cl.BaseClassScopeNum >= 0)
{
ai = AreaList.IndexOf(cl.BaseClassScopeNum);
if (ai >= 0)
AddToSymbolInfo(AreaList[ai].InfoList, cl.BaseClassScope, FirstInfo);
//cl=(ClassScope)ScopeTable[cl.BaseClassScopeNum];
ar = ScopeTable[cl.BaseClassScopeNum];
if (ar is DotNETScope)
{
AddToSymbolInfo(FirstInfo, (DotNETScope)ar, name);
return;
}
cl = (ClassScope)ScopeTable[cl.BaseClassScopeNum];
}
}
private Scope FindUnitInterfaceScope(Scope scope)
{
while (scope!=null && !(scope is UnitInterfaceScope))
scope = scope.TopScope;
return scope;
}
private Scope FindClassScope(Scope scope)
{
while (scope != null && !(scope is ClassScope))
if(scope is ClassMethodScope)
scope = ((ClassMethodScope)scope).MyClass;
else
scope = scope.TopScope;
return scope;
}
private bool IsInOneModule(Scope Scope1, Scope Scope2)
{
Scope1 = FindUnitInterfaceScope(Scope1);
Scope2 = FindUnitInterfaceScope(Scope2);
return (Scope1 != null) && (Scope2 != null) && (Scope1.ScopeNum == Scope2.ScopeNum);
}
private bool IsInOneOrDerivedClass(Scope IdentScope, Scope FromScope)
{
IdentScope = FindClassScope(IdentScope);
FromScope = FindClassScope(FromScope);
while (FromScope != null)
{
if (IdentScope.ScopeNum == FromScope.ScopeNum)
return true;
if (FromScope is ClassScope)
FromScope = ((ClassScope)FromScope).BaseClassScope;
else
FromScope = ((PascalABCCompiler.NetHelper.NetTypeScope)FromScope).TopScope;
}
return false;
}
private bool IsVisible(SymbolInfoUnit ident, Scope fromScope)
{
if (fromScope == null)
return true;
if (FindClassScope(ident.scope) == null)
return true;
switch (ident.access_level)
{
case access_level.al_public:
case access_level.al_internal:
return true;
case access_level.al_protected:
return IsInOneModule(ident.scope, fromScope) || IsInOneOrDerivedClass(ident.scope, fromScope);
case access_level.al_private:
return IsInOneModule(ident.scope, fromScope);
}
return true;
}
private bool IsNormal(SymbolInfoUnit to, SymbolInfoUnit add)
{
return //true;
(to == null) || (to.scope == null) || ((to.scope != null) && //to.scope == null не нужно?
(((to.symbol_kind == symbol_kind.sk_none) && (add.symbol_kind == symbol_kind.sk_none)) && (to.scope == add.scope))
||
((to.symbol_kind == symbol_kind.sk_overload_function) && (add.symbol_kind == symbol_kind.sk_overload_function))
||
((to.symbol_kind == symbol_kind.sk_overload_procedure) && (add.symbol_kind == symbol_kind.sk_overload_procedure))
);
}
private bool AlreadyAdded(SymbolInfoUnit si, SymbolInfoList FirstInfo)
{
if (FirstInfo.First() == null || si == null)
return false;
for (int i = 1; i < FirstInfo.InfoUnitList.Count; ++i)
if (FirstInfo.InfoUnitList[i] == si)
return true;
return false;
}
private SymbolInfoList AddToSymbolInfo(List<SymbolInfoUnit> from, Scope scope, SymbolInfoList FirstInfo)
{
bool CheckVisible = CurrentScope != null, NeedAdd = false;
SymbolInfoUnit to = FirstInfo.Last();
foreach (SymbolInfoUnit si_unit in from)
{
if (CheckVisible)
NeedAdd = IsVisible(si_unit, CurrentScope) && IsNormal(to, si_unit);
else
NeedAdd = IsNormal(to, si_unit);
if (NeedAdd && !AlreadyAdded(si_unit, FirstInfo))
{
FirstInfo.Add(si_unit);
to = si_unit;
}
}
LastScope=scope;
return to==null?null:new SymbolInfoList(to);
}
//Не используется ==> Не понятно работает или нет.
private SymbolInfoList AddToSymbolInfo(SymbolInfoList to, SymbolInfoList si, Scope scope)
{
if(si != null)
{
if(IsNormal(to.First(), si.First()))
{
SymbolInfoUnit temp = si.First();
to.Add(temp); si.InfoUnitList.RemoveRange(1, si.InfoUnitList.Count - 1);
LastScope = scope;
return si;
}
}
return to;
}
private SymbolInfoList AddToSymbolInfo(SymbolInfoList sito, DotNETScope ar, string name)
{
SymbolInfoList si = ar.Find(name);
if (si != null)
if (IsNormal(sito.Last(), si.First()))
{
sito.Add(si);
return si;
}
return sito;
}
private void FindAllInAreaList(string name, Scope[] arr, AreaNodesList AreaNodes,SymbolInfoList FirstInfo)
{
FindAllInAreaList(name, arr, AreaNodes, false, FirstInfo);
}
private void FindAllInAreaList(string name, Scope[] arr, AreaNodesList AreaNodes, bool StopIfFind, SymbolInfoList FirstInfo)
{
if (arr == null) return;
int p;
int add = FirstInfo.InfoUnitList.Count;
HashSet<Assembly> assm_cache = new HashSet<Assembly>();
foreach (Scope sc in arr)
{
if (sc is DotNETScope)
{
if (sc is PascalABCCompiler.NetHelper.NetScope)
{
PascalABCCompiler.NetHelper.NetScope netScope = sc as PascalABCCompiler.NetHelper.NetScope;
if (PascalABCCompiler.NetHelper.NetHelper.PABCSystemType == null || netScope.Assembly != PascalABCCompiler.NetHelper.NetHelper.PABCSystemType.Assembly)
{
if (!assm_cache.Contains(netScope.Assembly))
assm_cache.Add(netScope.Assembly);
else if (netScope.used_namespaces.Count == 0)
continue;
}
}
AddToSymbolInfo(FirstInfo, (DotNETScope)sc, name);
if (FirstInfo.InfoUnitList.Count > add && StopIfFind)
return;
}
else
if (AreaNodes != null && sc != null)
{
p = AreaNodes.IndexOf(sc.ScopeNum);
if (p >= 0)
{
AddToSymbolInfo(AreaNodes[p].InfoList, sc, FirstInfo);
if (FirstInfo.InfoUnitList.Count > add && StopIfFind)
return;
}
}
}
}
//поиск всех имен в ООВ.
// ищет наборы имен в ООВ, если находит то возвращает их список.
// иначе ищет в обьемлющем ООВ.
//SymbolInfo возвращаются в поряде в котором они встретились при проходе областей
public SymbolInfoList Find(Scope scope, string Name)
{
return FindAll(scope, Name, false, false, null);
}
public SymbolInfoList Find(Scope scope, string Name, Scope FromScope)
{
return FindAll(scope, Name, false, false, FromScope);
}
public SymbolInfoList FindOnlyInType(Scope scope, string Name)
{
//TODO: Почему ищет везде??? Только в типе и надтипах. А в юните он найдет?
return FindAll(scope, Name, true, false, null);
}
public SymbolInfoList FindOnlyInType(Scope scope, string Name, Scope FromScope)
{
return FindAll(scope, Name, true, false, FromScope);
}
public SymbolInfoList FindOnlyInThisClass(ClassScope scope, string Name)
{
return FindAll(scope, Name, true, true, null);
}
private SymbolInfoList FindAll(Scope scope, string Name, bool OnlyInType, bool OnlyInThisClass, Scope FromScope)
{
if (OnlyInType && !(scope is ClassScope) && !(scope is SymbolTable.DotNETScope)) return null;
//if (!CaseSensitive) Name=Name.ToLower();
if (!scope.CaseSensitive)
Name = Name.ToLower();
CurrentScope = FromScope; //глобальные переменные могут привести к ошибкам при поиске и поторном вызове!
LastScope = null; //глобальные переменные могут привести к ошибкам при поиске и поторном вызове!
SymbolInfoList FirstInfo = new SymbolInfoList(new SymbolInfoUnit());
int Area = scope.ScopeNum;
Scope[] used_units = null;
var tn = HashTable.Find(Name); //найдем имя в хеше
// SSM 21.01.16
if (Name.StartsWith("?")) // это значит, надо искать в областях .NET
Name = Name.Substring(1); // съели ? и ищем т.к. tn<0
// end SSM
if (tn == null || scope is DotNETScope)//если нет такого ищем в областях .NET
{
//ssyy
int NextUnitArea = -2;
//\ssyy
Scope an;
while (Area >= 0)
{
an = ScopeTable[Area];
if (an is DotNETScope)
{
if (tn == null)
{
AddToSymbolInfo(FirstInfo, (DotNETScope)an, Name);
}
else
{
FindAllInClass(Name, Area, tn.NumAreaList, false, FirstInfo);
}
}
if (FirstInfo.InfoUnitList.Count > 1)
{
FirstInfo.InfoUnitList.RemoveAt(0);
return FirstInfo;
}
if (an is UnitPartScope)
{
if (an is UnitImplementationScope)
{
FindAllInAreaList(Name, (an as UnitImplementationScope).TopScopeArray, null, FirstInfo);
an = ScopeTable[an.TopScopeNum];
}
FindAllInAreaList(Name, (an as UnitInterfaceScope).TopScopeArray, null, FirstInfo);
if (FirstInfo.InfoUnitList.Count > 1)
{
FirstInfo.InfoUnitList.RemoveAt(0);
return FirstInfo;
}
}
if (an is WithScope)//мы очутились в Width
{
FindAllInAreaList(Name, (an as WithScope).WithScopes, null, true, FirstInfo);
if (FirstInfo.InfoUnitList.Count > 1) //если что-то нашли то заканчиваем
{
FirstInfo.InfoUnitList.RemoveAt(0);
return FirstInfo;
}
}
if (an is ClassScope)
{
int unit_area = an.TopScopeNum;
InterfaceScope IntScope = an as InterfaceScope;
while (((ClassScope)an).BaseClassScopeNum >= 0)
{
an = ScopeTable[((ClassScope)an).BaseClassScopeNum];
if (an is DotNETScope)
{
AddToSymbolInfo(FirstInfo, (DotNETScope)an, Name);
if (FirstInfo.InfoUnitList.Count > 1) // || OnlyInType)
{
FirstInfo.InfoUnitList.RemoveAt(0);
return FirstInfo;
}
break;
}
}
//В предках ничего не нашли, ищем по интерфейсам...
if (IntScope != null)
{
FindAllInAreaList(Name, IntScope.TopInterfaceScopeArray, null, FirstInfo);
if (FirstInfo.InfoUnitList.Count > 1) //если что-то нашли то заканчиваем
{
FirstInfo.InfoUnitList.RemoveAt(0);
return FirstInfo;
}
}
if (OnlyInType)
{
FirstInfo.InfoUnitList.RemoveAt(0);
return FirstInfo.InfoUnitList.Count > 0 ? FirstInfo : null;
}
//ssyy
if (NextUnitArea > -1)
{
Area = NextUnitArea;
//NextUnitArea = -2;
continue;
}
else
//\ssyy
an = ScopeTable[unit_area];
}
if (FirstInfo.InfoUnitList.Count > 1)
{
FirstInfo.InfoUnitList.RemoveAt(0);
return FirstInfo;
}
if (an is ClassMethodScope)
{
//ssyy
NextUnitArea = an.TopScopeNum;
//\ssyy
Area = (an as ClassMethodScope).MyClassNum;
}
else
{
Area = GetTopScopeNum(Area);
}
//Area=GetTopScopeNum(Area);
}
return null; //если такого нет то поиск окончен
}
AreaNodesList AreaList = tn.NumAreaList;
int CurrentArea = Area, ai;
while (CurrentArea >= 0)
{
if (ScopeTable[CurrentArea] is UnitPartScope) //мы очутились в модуле
{
//мы в ImplementationPart?
if (ScopeTable[CurrentArea] is UnitImplementationScope)
{
used_units = (ScopeTable[CurrentArea] as UnitImplementationScope).TopScopeArray;
ai = AreaList.IndexOf(CurrentArea);
if (ai >= 0) //что-то нашли!
{
AddToSymbolInfo(AreaList[ai].InfoList, ScopeTable[CurrentArea], FirstInfo);
}
CurrentArea = GetTopScopeNum(CurrentArea);
}
//сейча мы в InterfacePart
ai = AreaList.IndexOf(CurrentArea);
if (ai >= 0) //что-то нашли!
{
AddToSymbolInfo(AreaList[ai].InfoList, ScopeTable[CurrentArea], FirstInfo);
}
//смотрим в модулях
FindAllInAreaList(Name, used_units, AreaList, FirstInfo);
FindAllInAreaList(Name, (ScopeTable[CurrentArea] as UnitInterfaceScope).TopScopeArray, AreaList, FirstInfo);
FirstInfo.InfoUnitList.RemoveAt(0);
return FirstInfo.InfoUnitList.Count > 0 ? FirstInfo : null;
}
else
if (ScopeTable[CurrentArea] is IInterfaceScope)
{
FindAllInClass(Name, CurrentArea, AreaList, OnlyInThisClass, FirstInfo);
if (FirstInfo.InfoUnitList.Count > 1) //если что-то нашли то заканчиваем
{
FirstInfo.InfoUnitList.RemoveAt(0);
return FirstInfo;
}
//Зачем искать в интерфейсах?
//(ssyy) Не понимаю вопрос. Спросившему подумать, зачем в компиляторе нужен поиск.
FindAllInAreaList(Name, (ScopeTable[CurrentArea] as IInterfaceScope).TopInterfaceScopeArray, AreaList, FirstInfo);
if (FirstInfo.InfoUnitList.Count > 1 || OnlyInType) //если что-то нашли то заканчиваем
{
FirstInfo.InfoUnitList.RemoveAt(0);
return FirstInfo.InfoUnitList.Count > 0 ? FirstInfo : null;
}
}
else
if (ScopeTable[CurrentArea] is ClassScope)//мы очутились в классе
{
FindAllInClass(Name, CurrentArea, AreaList, OnlyInThisClass, FirstInfo);//надо сделать поиск по его предкам
if (FirstInfo.InfoUnitList.Count > 1 || OnlyInType) //если что-то нашли то заканчиваем
{
FirstInfo.InfoUnitList.RemoveAt(0);
return FirstInfo.InfoUnitList.Count > 0 ? FirstInfo : null;
}
//иначе ищем дальше
}
else
if (ScopeTable[CurrentArea] is WithScope)//мы очутились в With
{
ai = AreaList.IndexOf(CurrentArea);
if (ai >= 0) //что-то нашли!
{
AddToSymbolInfo(AreaList[ai].InfoList, ScopeTable[CurrentArea], FirstInfo);
}
if (FirstInfo.InfoUnitList.Count > 1) //если что-то нашли то заканчиваем
{
FirstInfo.InfoUnitList.RemoveAt(0);
return FirstInfo;
}
Scope[] wscopes = (ScopeTable[CurrentArea] as WithScope).WithScopes;
if (wscopes != null)
foreach (Scope wsc in wscopes)
{
FindAllInClass(Name, wsc.ScopeNum, AreaList, OnlyInThisClass, FirstInfo);//надо сделать поиск по его предкам
if (FirstInfo.InfoUnitList.Count > 1) //если что-то нашли то заканчиваем
{
FirstInfo.InfoUnitList.RemoveAt(0);
return FirstInfo;
}
}
//info = FindAllInAreaList(info, Name, (ScopeTable[CurrentArea] as WithScope).WithScopes, AreaList, true);
}
else
{
ai = AreaList.IndexOf(CurrentArea);
if (ai >= 0) //что-то нашли!
{
AddToSymbolInfo(AreaList[ai].InfoList, ScopeTable[CurrentArea], FirstInfo);
FirstInfo.InfoUnitList.RemoveAt(0);
return FirstInfo.InfoUnitList.Count > 0 ? FirstInfo : null;
}
if (ScopeTable[CurrentArea] is ClassMethodScope)//мы очутились в методе класса
{
FindAllInClass(Name, (ScopeTable[CurrentArea] as ClassMethodScope).MyClassNum, AreaList, OnlyInThisClass, FirstInfo);//надо сделать поиск по его классу
if (FirstInfo.InfoUnitList.Count > 1) //если что-то нашли то заканчиваем
{
FirstInfo.InfoUnitList.RemoveAt(0);
return FirstInfo;
}
}
}
CurrentArea = GetTopScopeNum(CurrentArea);//Пошли вверх
}
return null;
}
}
public class TreeConverterSymbolTable:DSSymbolTable
{
public TreeConverterSymbolTable(bool case_sensitive):base(SymbolTableConstants.HashTable_StartSize,case_sensitive){}
public TreeConverterSymbolTable():base(SymbolTableConstants.HashTable_StartSize,false){}
}
public class SymbolTableController
{
public static TreeConverterSymbolTable CurrentSymbolTable = new TreeConverterSymbolTable();
}
}