// 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.Collections.Generic;
using PascalABCCompiler.TreeConverter;
using PascalABCCompiler.TreeRealization;
using System.Linq;
namespace PascalABCCompiler.TreeRealization
{
///
/// Базовый класс для представления пространств имен.
///
[Serializable]
public abstract class namespace_node : definition_node, SemanticTree.INamespaceNode
{
///
/// Полное имя пространства имен.
///
public abstract string namespace_full_name
{
get;
}
///
/// Поиск символа в пространстве имен.
///
/// Имя элемента для поиска.
/// Информация о найденном символе. null, если ни чего не найдено.
public abstract List find(string name);
public abstract List findOnlyInNamespace(string name);
///
/// Имя пространства имен.
///
public abstract string namespace_name
{
get;
}
///
/// Метод для обхода дерева посетителем.
///
/// Класс - посетитель дерева.
public override void visit(SemanticTree.ISemanticVisitor visitor)
{
visitor.visit(this);
}
///
/// Обобщенный тип узла.
///
public override general_node_type general_node_type
{
get
{
return general_node_type.namespace_node;
}
}
}
///
/// Класс, представляющий обычное пространство имен.
///
[Serializable]
public class common_namespace_node : namespace_node, SemanticTree.ICommonNamespaceNode
{
public override string ToString()
{
if(is_main)
return "main";
if (namespace_full_name == "")
return GetType().Name;
return namespace_full_name;
}
///
/// Список типов, вложенных в пространство имен.
///
private readonly common_type_node_list _types=new common_type_node_list();
//ssyy добавил
///
/// Список шаблонных классов, вложенных в пространство имен.
///
private readonly template_class_list _templates = new template_class_list();
//\ssyy
//ssyy добавил
///
/// Список определённых в пространстве имен синонимов типов.
///
private readonly List _type_synonyms = new List();
//\ssyy
///
/// Список определённых в пространстве имен типов-указателей.
///
private readonly List _ref_types = new List();
///
/// Список runtime типов, вложенных в пространство имен.
///
private readonly compiled_type_node_list _runtime_types = new compiled_type_node_list();
///
/// Список переменных, определенных в прстранстве имен.
///
private readonly namespace_variable_list _variables = new namespace_variable_list();
private readonly namespace_event_list _events = new namespace_event_list();
///
/// Список меток, определенных в прстранстве имен.
///
private readonly List _labels = new List();
///
/// Список функций, определенных в пространстве имен.
///
private readonly common_namespace_function_node_list _functions = new common_namespace_function_node_list();
///
/// Список констант, определенных в пространстве имен.
///
private readonly namespace_constant_definition_list _constants=new namespace_constant_definition_list();
///
/// Список пространств имен, вложенных в пространство имен.
///
private readonly common_namespace_node_list _namespaces= new common_namespace_node_list();
///
/// Пространство имен, в которое вложено это пространство имен.
///
private namespace_node _comprehensive_namespace;
///
/// Модуль, в котором содержится это пространство имен.
/// При генерации кода, когда возможна ситуация при которой простраство имен расположено в нескольких модулях,
/// этот элемент указывает на один из модулей в котором встретилось это пространство имен.
///
private unit_node _cont_unit;
///
/// Имя пространства имен.
///
private string _name;
///
/// Область видимости пространства имен.
///
private SymbolTable.Scope _scope;
///
/// Расположения заголовка пространства имен.
///
private location _loc;
///
/// Конструктор узла.
///
/// Пространство имен, в которое вложено это пространство имен.
/// Модуль, в котором содержится это пространство имен.
/// Имя пространства имен.
/// Область видимости пространства имен.
/// Расположения заголовка пространства имен.
public common_namespace_node(namespace_node comprehensive_namespace, unit_node cont_unit, string name,
SymbolTable.Scope scope, location loc)
{
_comprehensive_namespace = comprehensive_namespace;
_cont_unit = cont_unit;
_name = name;
_scope = scope;
_loc = loc;
}
///
/// Клонирует пространство имен.
///
/// Копия пространства иен.
public common_namespace_node clone()
{
common_namespace_node cnn = new common_namespace_node(this._comprehensive_namespace, this._cont_unit,
this._name, this._scope, this._loc);
cnn.merge_with_namespace(this);
return cnn;
}
///
/// Добавляет к текущему пространству имен указанное пространство имен.
///
/// Пространство имен для добавления.
public void merge_with_namespace(common_namespace_node merge_with)
{
_types.AddRange(merge_with._types);
//ssyy
_templates.AddRange(merge_with._templates);
_type_synonyms.AddRange(merge_with._type_synonyms);
//\ssyy
_variables.AddRange(merge_with._variables);
_functions.AddRange(merge_with._functions);
_constants.AddRange(merge_with._constants);
_namespaces.AddRange(merge_with._namespaces);
}
private bool _is_main;
public bool is_main
{
get
{
return _is_main;
}
set
{
_is_main = value;
}
}
bool SemanticTree.ICommonNamespaceNode.IsMain
{
get
{
return _is_main;
}
}
///
/// Область видимости пространства имен.
///
public SymbolTable.Scope scope
{
get
{
return _scope;
}
set
{
_scope = value;
}
}
///
/// Расположения заголовка пространства имен.
///
public location loc
{
get
{
return _loc;
}
}
///
/// Расположения заголовка пространства имен.
/// Используется при обходе дерева посетителем.
///
public SemanticTree.ILocation Location
{
get
{
return _loc;
}
}
///
/// Имя пространства имен.
///
public override string namespace_name
{
get
{
return _name;
}
}
public void SetNamespaceName(string name)
{
_name = name;
}
///
/// Пространство имен, в которое вложено это пространство имен.
///
public namespace_node comprehensive_namespace
{
get
{
return _comprehensive_namespace;
}
}
///
/// Модуль, в котором содержится это пространство имен.
/// При генерации кода, когда возможна ситуация при которой простраство имен расположено в нескольких модулях,
/// этот элемент указывает на один из модулей в котором встретилось это пространство имен.
///
public unit_node cont_unit
{
get
{
return _cont_unit;
}
}
///
/// Список типов, вложенных в пространство имен.
///
public common_type_node_list types
{
get
{
return _types;
}
}
//ssyy добавил
///
/// Список шаблонных классов, вложенных в пространство имен.
///
public template_class_list templates
{
get
{
return _templates;
}
}
///
/// Список определённых в пространстве имен синонимов типов.
///
public List type_synonyms
{
get
{
return _type_synonyms;
}
}
//\ssyy
///
/// Список определённых в пространстве имен типов-указателей.
///
public List ref_types
{
get
{
return _ref_types;
}
}
///
/// Список типов, вложенных в пространство имен.
///
public compiled_type_node_list runtime_types
{
get
{
return _runtime_types;
}
}
///
/// Список пространств имен, вложенных в пространство имен.
///
public common_namespace_node_list namespaces
{
get
{
return _namespaces;
}
}
///
/// Список переменных, определенных в прстранстве имен.
///
public namespace_variable_list variables
{
get
{
return _variables;
}
}
public namespace_event_list events
{
get
{
return _events;
}
}
///
/// Список меток, определенных в прстранстве имен.
///
public List labels
{
get
{
return _labels;
}
}
///
/// Список функций, определенных в пространстве имен.
///
public common_namespace_function_node_list functions
{
get
{
return _functions;
}
}
///
/// Список констант, определенных в пространстве имен.
///
public namespace_constant_definition_list constants
{
get
{
return _constants;
}
}
///
/// Полное имя пространства имен.
///
public override string namespace_full_name
{
get
{
if (_comprehensive_namespace==null)
{
return _name;
}
return (_comprehensive_namespace.namespace_full_name+"."+_name);
}
}
private bool _from_pcu;
public bool from_pcu
{
get
{
return _from_pcu;
}
set
{
_from_pcu = value;
}
}
///
/// Поиск символа в этом пространстве имен.
///
/// Искомое имя.
/// Информация о найденом символе. null, если ни чего не найдена.
public override List find(string name)
{
return _scope.Find(name);//c,cc,c,cc
}
public SymbolInfo findFirstOnlyInNamespace(string name)
{
var temp = _scope.FindOnlyInScope(name);//c,cc,c,cc
return temp?.First();
}
public override List findOnlyInNamespace(string name)
{
List si_list = _scope.FindOnlyInScope(name);//c,cc,c,cc
return si_list;
}
///
/// Тип узла.
///
public override semantic_node_type semantic_node_type
{
get
{
return semantic_node_type.common_namespace_node;
}
}
///
/// Метод для обхода дерева посетителем.
///
/// Класс - посетитель дерева.
public override void visit(SemanticTree.ISemanticVisitor visitor)
{
visitor.visit(this);
}
SemanticTree.ICommonNamespaceNode[] SemanticTree.ICommonNamespaceNode.nested_namespaces
{
get
{
return (this._namespaces.ToArray());
}
}
SemanticTree.ICommonTypeNode[] SemanticTree.ICommonNamespaceNode.types
{
get
{
return (this._types.ToArray());
}
}
SemanticTree.ITypeSynonym[] SemanticTree.ICommonNamespaceNode.type_synonims
{
get
{
return this._type_synonyms.ToArray();
}
}
SemanticTree.ITemplateClass[] SemanticTree.ICommonNamespaceNode.templates
{
get
{
return this.templates.ToArray();
}
}
SemanticTree.ICommonNamespaceVariableNode[] SemanticTree.ICommonNamespaceNode.variables
{
get
{
return (this._variables.ToArray());
}
}
SemanticTree.ICommonNamespaceEventNode[] SemanticTree.ICommonNamespaceNode.events
{
get
{
return (this._events.ToArray());
}
}
SemanticTree.ICommonNamespaceFunctionNode[] SemanticTree.ICommonNamespaceNode.functions
{
get
{
return (this._functions.ToArray());
}
}
SemanticTree.INamespaceNode SemanticTree.ICommonNamespaceNode.comprehensive_namespace
{
get
{
return (this._comprehensive_namespace);
}
}
SemanticTree.INamespaceConstantDefinitionNode[] SemanticTree.ICommonNamespaceNode.constants
{
get
{
return (this._constants.ToArray());
}
}
//(ssyy) Флаг, чтобы не проверять второй раз наличие тел всех описанных функций
public bool predefinitions_checked = false;
//(ssyy) Набор типов для сохранения на диск
private common_type_node_list _non_template_types = null;
public common_type_node_list non_template_types
{
get
{
return _non_template_types;
}
}
public void MakeNonTemplateTypesList()
{
_non_template_types = new common_type_node_list();
foreach (common_type_node ctn in _types)
{
if (ctn.original_template == null)
{
_non_template_types.AddElement(ctn);
}
}
}
}
///
/// Класс, представляющий пространство имен в откомпилированном коде.
///
[Serializable]
public class compiled_namespace_node : namespace_node, SemanticTree.ICompiledNamespaceNode
{
///
/// Имя (полное) пространства имен.
///
private string _name;
private common_namespace_node _common_namespace;
private SymbolTable.Scope _scope;
private SymbolTable.TreeConverterSymbolTable _tcst;
///
/// Конструктор узла.
///
/// Полное имя пространства имен.
public compiled_namespace_node(string name, SymbolTable.TreeConverterSymbolTable tcst)
{
_name=name;
_tcst = tcst;
using_namespace_list unl = new using_namespace_list();
unl.AddElement(new using_namespace(_name));
_scope = new NetHelper.NetScope(unl, _tcst);
}
///
/// Получение имени пространства имен по его полному имени.
///
/// Полное имя пространства имен.
/// Имя пространства имен.
private string get_namespace_name(string full_name)
{
int last_dot_ind = full_name.LastIndexOf('.');
if (last_dot_ind < 0)
{
return _name;
}
return new string(_name.ToCharArray(last_dot_ind,_name.Length-last_dot_ind));
}
private static Dictionary compiled_namespaces = new Dictionary();
public static compiled_namespace_node get_compiled_namespace(string full_name, SymbolTable.TreeConverterSymbolTable tcst)
{
compiled_namespace_node cnn = null;
if (!compiled_namespaces.TryGetValue(full_name, out cnn))
{
cnn = new compiled_namespace_node(full_name, tcst);
compiled_namespaces.Add(full_name, cnn);
}
cnn._tcst = tcst;
return cnn;
}
public SymbolTable.TreeConverterSymbolTable SymbolTable
{
get
{
return _tcst;
}
}
public SymbolTable.Scope scope
{
get
{
return _scope;
}
}
///
/// Имя пространства имен (не полное).
///
public override string namespace_name
{
get
{
return get_namespace_name(_name);
}
}
///
/// Полное имя пространства имен.
///
public override string namespace_full_name
{
get
{
return _name;
}
}
public common_namespace_node common_namespace
{
get
{
return _common_namespace;
}
set
{
_common_namespace = value;
}
}
public override List findOnlyInNamespace(string name)
{
return find(name);
}
///
/// Поиск символа в пространстве имен.
///
/// Имя для поиска.
/// Первый элемент списка найденных имен. null если ни чего не найдено.
public override List find(string name)
{
bool is_ns = NetHelper.NetHelper.IsNetNamespace(_name + "." + name);
List sil = null;
if (is_ns)
{
compiled_namespace_node cnn = compiled_namespace_node.get_compiled_namespace(_name + "." + name, _tcst);
sil = new List { new SymbolInfo(cnn) };
}
else
{
//Kolay changed next string. throwOnError=false ignoreCase=true, .
//Type t = Type.GetType(_name+"."+name,false,true);
if (common_namespace != null)
{
sil = common_namespace.scope.FindOnlyInScope(name);
if (sil != null)
return sil;
}
Type t = NetHelper.NetHelper.FindType(_name + "." + name);
if (t != null)
{
sil = new List { new SymbolInfo(compiled_type_node.get_type_node(t, _tcst)) };
}
else
{
t = NetHelper.NetHelper.FindType(_name+"."+_name);
if (t != null && NetHelper.NetHelper.IsEntryType(t))
{
sil = NetHelper.NetHelper.FindName(t,name);
if (sil == null)
{
type_node tn = NetHelper.NetHelper.FindCompiledPascalType(_name + "." + name);
if (tn != null)
sil = new List { new SymbolInfo(tn) };
else
{
template_class tc = NetHelper.NetHelper.FindCompiledTemplateType(_name + "." + name);
if (tc != null)
sil = new List { new SymbolInfo(tc) };
}
}
}
}
}
return sil;
}
///
/// Тип узла.
///
public override semantic_node_type semantic_node_type
{
get
{
return semantic_node_type.compiled_namespace_node;
}
}
///
/// Метод для обхода дерева посетителем.
///
/// Класс - посетитель дерева.
public override void visit(SemanticTree.ISemanticVisitor visitor)
{
visitor.visit(this);
}
}
}
namespace PascalABCCompiler.SyntaxTree
{
public class syntax_namespace_node : base_syntax_namespace_node
{
PascalABCCompiler.TreeRealization.unit_node_list _referenced_units;
public syntax_namespace_node(string name):base(name)
{
}
public unit_node_list referenced_units { get => _referenced_units; set => _referenced_units = value; }
}
}