pascalabcnet/TreeConverter/TreeRealization/templates.cs

657 lines
20 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 Mikhalkovich (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
//Здесь описана реализация неуправляемых шаблонов
//Файлом владеет ssyy.
using System;
using System.Collections.Generic;
using PascalABCCompiler.TreeConverter;
using System.Linq;
namespace PascalABCCompiler.TreeRealization
{
//Хранит информацию о методе, описанном вне класса
public class procedure_definition_info
{
//Пространство, где метод описан
public common_namespace_node nspace;
//Сам метод в виде синтаксического дерева
public SyntaxTree.procedure_definition proc;
public procedure_definition_info(common_namespace_node _nspace,
SyntaxTree.procedure_definition _proc)
{
nspace = _nspace;
proc = _proc;
}
}
public class template_class : definition_node, PascalABCCompiler.SemanticTree.ITemplateClass
{
public override string ToString() => type_dec.type_name + "=" + type_dec.type_def.ToString();
public static bool check_template_definitions = true;
public static bool TypeDependedFromTemplate(type_node tn)
{
common_type_node ctn = tn as common_type_node;
if (ctn == null)
{
return false;
}
if (ctn.original_template != null)
{
return true;
}
switch (tn.type_special_kind)
{
case PascalABCCompiler.SemanticTree.type_special_kind.array_kind:
case PascalABCCompiler.SemanticTree.type_special_kind.set_type:
//case PascalABCCompiler.SemanticTree.type_special_kind.typed_file:
return TypeDependedFromTemplate(tn.element_type);
}
return false;
}
public static void AddUsingListToScope(SymbolTable.Scope scope, using_namespace_list unl)
{
SymbolTable.UnitPartScope ups = scope as SymbolTable.UnitPartScope;
if (ups == null) return;
foreach (SymbolTable.Scope sc in ups.TopScopeArray)
{
NetHelper.NetScope netsc = sc as NetHelper.NetScope;
if (netsc != null && netsc.used_namespaces.Count == 0)
{
using_namespace_list new_unl = new using_namespace_list();
foreach (using_namespace un in unl)
{
List<SymbolInfo> sil = netsc.FindOnlyInScope(un.namespace_name);
if ((sil.FirstOrDefault().sym_info as compiled_namespace_node) != null)
{
new_unl.AddElement(un);
}
}
netsc.used_namespaces = new_unl;
}
}
}
//добавит, если такого нет
public string GetTemplateInstanceName(List<type_node> instance_params)
{
string rez = _name;
bool first = true;
foreach (type_node tnode in instance_params)
{
rez += ((first) ? "<" : ",") + tnode.name;
first = false;
}
//(ssyy!!!) Проверить корректность наличия символа запятая в имени
rez += ">";
if (!_instances.ContainsKey(rez))
{
List<List<type_node>> tlist = new List<List<type_node>>();
tlist.Add(instance_params);
_instances.Add(rez, tlist);
return rez;
}
else
{
List<List<type_node>> inst = _instances[rez];
for (int i = 0; i < inst.Count; i++)
{
bool equal = true;
for (int j = 0; j < instance_params.Count; j++)
{
if (inst[i][j] != instance_params[j])
{
equal = false;
}
}
if (equal)
{
return (i == 0) ? rez : (rez + '$' + i.ToString());
}
}
inst.Add(instance_params);
return rez + '$' + (inst.Count - 1).ToString();
}
}
public List<type_node> GetParamsList(common_type_node template_instance)
{
/*string key = instance_name;
int num = 0;
if (instance_name[instance_name.Length - 1] != '>')
{
int i = instance_name.Length - 1;
while (instance_name[i] != '$')
{
i--;
}
string snum = instance_name.Substring(i + 1);
num = Convert.ToInt32(snum);
key = instance_name.Substring(0, i);
}
List<List<type_node>> founded = _instances[key];
return founded[num];*/
List<type_node> i_params;
if (_instance_params.TryGetValue(template_instance, out i_params))
{
return i_params;
}
else
{
return null;
}
}
private SyntaxTree.type_declaration _type_decl; //Синтаксическое дерево шаблона
private string _name; //Имя шаблона
private common_namespace_node _cnn; //Пространство, где описан шаблон
private string _file_name; //Документ, т.е. файл, где описан шаблон
private using_namespace_list _unl; //Список подключенных к _cnn пространств
private using_namespace_list _unl2 = null; //То же для пространства внешних методов
private bool _ForwardDeclarationOnly = false; //true, если пока есть только предописание
private bool _is_synonym = false; //true, если синоним шаблонного типа
public bool is_synonym
{
get { return _is_synonym; }
set { _is_synonym = value; }
}
//Список методов, определённых вне шаблонного класса
private List<procedure_definition_info> _external_methods = new List<procedure_definition_info>();
private Dictionary<string, List<List<type_node>>> _instances = new Dictionary<string, List<List<type_node>>>();
private Dictionary<common_type_node, List<type_node>> _instance_params = new Dictionary<common_type_node, List<type_node>>();
public string CreateTemplateInstance(List<type_node> instance_params, location loc)
{
SyntaxTree.class_definition cl_def = _type_decl.type_def as SyntaxTree.class_definition;
SyntaxTree.template_type_name ttn = _type_decl.type_name as SyntaxTree.template_type_name;
//if (cl_def == null)
//{
// throw new PascalABCCompiler.TreeConverter.CompilerInternalError("No body definition in template class.");
//}
//if (cl_def.template_args == null || cl_def.template_args.idents == null)
//{
// throw new PascalABCCompiler.TreeConverter.CompilerInternalError("No template arguments in syntax tree.");
//}
List<SyntaxTree.ident> template_formals = (_is_synonym) ?
ttn.template_args.idents : cl_def.template_args.idents;
if (instance_params.Count != template_formals.Count)
{
throw new PascalABCCompiler.TreeConverter.SimpleSemanticError(loc, "TEMPLATE_ARGUMENTS_COUNT_MISMATCH");
}
return GetTemplateInstanceName(instance_params);
}
public SyntaxTree.type_declaration type_dec
{
get
{
return _type_decl;
}
set
{
_type_decl = value;
}
}
public string name
{
get
{
return _name;
}
}
public common_namespace_node cnn
{
get
{
return _cnn;
}
}
public string cur_document
{
get
{
return _file_name;
}
}
public using_namespace_list using_list
{
get
{
return _unl;
}
}
public using_namespace_list using_list2
{
get
{
return _unl2;
}
set
{
_unl2 = value;
}
}
public bool ForwardDeclarationOnly
{
get
{
return _ForwardDeclarationOnly;
}
set
{
_ForwardDeclarationOnly = value;
}
}
public List<procedure_definition_info> external_methods
{
get
{
return _external_methods;
}
set
{
_external_methods = value;
}
}
public Dictionary<common_type_node, List<type_node>> instance_params
{
get
{
return _instance_params;
}
}
public template_class(SyntaxTree.type_declaration type_decl, string name,common_namespace_node cnn,/*common_type_node ctn,location loc,*/string file_name,using_namespace_list unl)
{
_cnn = cnn;
_type_decl = type_decl;
_name = name;
_file_name = file_name;
//(ssyy) using - список, по-видимому, можно только копировать, т.к. Николай его периодически чистит.
_unl = new using_namespace_list();
foreach (using_namespace un in unl)
{
_unl.AddElement(un);
}
}
public override general_node_type general_node_type
{
get
{
return general_node_type.template_type;
}
}
public override semantic_node_type semantic_node_type
{
get
{
return semantic_node_type.template_type;
}
}
/// <summary>
/// Метод для обхода дерева посетителем.
/// </summary>
/// <param name="visitor">Класс - посетитель дерева.</param>
public override void visit(SemanticTree.ISemanticVisitor visitor)
{
throw new PascalABCCompiler.TreeConverter.CompilerInternalError("Template class can't be visit.");
}
private byte[] tree=null;
public byte[] serialized_tree
{
get
{
if (!this.is_synonym)
return null;
if (tree == null)
try
{
SyntaxTree.SyntaxTreeStreamWriter stw = new SyntaxTree.SyntaxTreeStreamWriter();
byte[] buf = new byte[10000];
stw.bw = new System.IO.BinaryWriter(new System.IO.MemoryStream(buf));
this.type_dec.visit(stw);
tree = new byte[(int)stw.bw.BaseStream.Position+1];
tree[0] = 1;
Array.Copy(buf, 0, tree, 1, (int)stw.bw.BaseStream.Position);
}
catch (Exception ex)
{
}
return tree;
}
}
}
//члены неопределенного типа (типовой переменной)
public class indefinite_definition_node : function_node
{
private type_node _cont_class;
public type_node cont_class
{
get { return _cont_class; }
}
private string _name;
public override string name
{
get { return _name; }
}
public indefinite_definition_node(string node_name, type_node connected_class)
{
_name = node_name;
_cont_class = connected_class;
return_value_type = new indefinite_type_node();
}
public override general_node_type general_node_type
{
get { return general_node_type.function_node; }
}
public override semantic_node_type semantic_node_type
{
get { return semantic_node_type.indefinite_definition_node; }
}
public override PascalABCCompiler.SemanticTree.node_kind node_kind
{
get { return PascalABCCompiler.SemanticTree.node_kind.indefinite; }
}
public override PascalABCCompiler.SemanticTree.node_location_kind node_location_kind
{
get { return PascalABCCompiler.SemanticTree.node_location_kind.indefinite; }
}
}
public class indefinite_functions_set : indefinite_definition_node
{
private List<function_node> _functions = null;
public List<function_node> functions
{
get { return _functions; }
set { _functions = value; }
}
public void Add(function_node function)
{
if (_functions == null)
{
_functions = new List<function_node>();
}
_functions.Add(function);
UpdateReturnType();
}
public indefinite_functions_set()
: base(null, null)
{
return_value_type = null;
}
public indefinite_functions_set(List<function_node> functions)
: base(null, null)
{
_functions = functions;
UpdateReturnType();
}
private bool _ret_type_generated = false;
public void UpdateReturnType()
{
if (!_ret_type_generated)
{
type_node tn = _functions[0].return_value_type;
int i = 1;
while (i < _functions.Count)
{
if (_functions[i].return_value_type == tn)
++i;
else
break;
}
if (i == _functions.Count)
{
return_value_type = tn;
}
else
{
_ret_type_generated = true;
return_value_type = new indefinite_type_node();
}
}
}
}
//класс для представления неопределенных типов (вспомогательных типовых переменных)
public class indefinite_type_node : type_node
{
private string _name;
public indefinite_type_node()
{
_name = "$it";
}
public indefinite_type_node(string name)
{
_name = name;
}
//public static List<type_node> get_indefinite_type_list(int count)
//{
// List<type_node> rez = new List<type_node>(count);
// for (int i = 0; i < count; i++)
// {
// rez.Add(new indefinite_type_node());
// }
// return rez;
//}
public override SymbolInfo find_first_in_type(string name, bool no_search_in_extension_methods = false)
{
indefinite_definition_node idn = new indefinite_definition_node(name, this);
return new SymbolInfo(idn, access_level.al_public, symbol_kind.sk_indefinite);
}
public override List<SymbolInfo> find_in_type(string name, bool no_search_in_extension_methods = false)
{
indefinite_definition_node idn = new indefinite_definition_node(name, this);
return new List<SymbolInfo> { new SymbolInfo(idn, access_level.al_public, symbol_kind.sk_indefinite) };
}
public override List<SymbolInfo> find(string name, bool no_search_in_extension_methods = false)
{
return find_in_type(name);
}
public override void add_name(string name, SymbolInfo si)
{
//ничего не делаем
}
public override void add_generated_name(string name, SymbolInfo si)
{
//ничего не делаем
}
public override void clear_generated_names()
{
//ничего не делаем
}
public override void SetName(string name)
{
//ничего не делаем;
}
public override type_node base_type
{
get { return SystemLibrary.SystemLibrary.object_type; }
}
public override string name
{
get { return _name; }
}
public override string full_name
{
get { return _name; }
}
public override property_node default_property_node
{
get { return null; }
}
public override PascalABCCompiler.SemanticTree.node_kind node_kind
{
get { return SemanticTree.node_kind.indefinite; }
}
public override SymbolTable.Scope Scope
{
get { return null; }
}
public override bool is_class
{
get
{
return false;
}
set
{
}
}
public override bool is_value
{
get { return false; }
}
public override PascalABCCompiler.SemanticTree.type_special_kind type_special_kind
{
get
{
return PascalABCCompiler.SemanticTree.type_special_kind.none_kind;
}
set
{
}
}
public override semantic_node_type semantic_node_type
{
get { return semantic_node_type.indefinite_type; }
}
public override bool depended_from_indefinite
{
get
{
return true;
}
}
}
//public class indefinite_expression_node : expression_node
//{
// public indefinite_expression_node(location loc)
// {
// this.type = new indefinite_type_node();
// this.location = loc;
// }
// public indefinite_expression_node(type_node tn, location loc)
// : base(tn, loc)
// {
// }
// public override semantic_node_type semantic_node_type
// {
// get { return semantic_node_type.indefinite_expression_node; }
// }
//}
public class indefinite_function_call : base_function_call
{
function_node _function_node;
public indefinite_function_call(function_node fn, location loc)
: base(fn.return_value_type, loc)
{
_function_node = fn;
}
public override function_node simple_function_node
{
get { return _function_node; }
}
public override semantic_node_type semantic_node_type
{
get { return semantic_node_type.indefinite_function_call; }
}
}
public class indefinite_reference : addressed_expression
{
private indefinite_definition_node _indefinite_def;
public indefinite_definition_node indefinite_def
{
get { return _indefinite_def; }
}
public indefinite_reference(indefinite_definition_node idn, location loc)
: base(idn.cont_class, loc)
{
_indefinite_def = idn;
}
public override semantic_node_type semantic_node_type
{
get { return semantic_node_type.indefinite_reference; }
}
}
}