* Fix result variable case sensitive comparing * Make code shorter * Refactor code again * Add ToLower in LambdaHelper
4143 lines
192 KiB
C#
4143 lines
192 KiB
C#
// 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)
|
||
//Класс, хранящий текущий контекст. Где находится компилятор (в какой функции, типе, пространстве имен).
|
||
using System;
|
||
using System.Linq;
|
||
using PascalABCCompiler.TreeRealization;
|
||
using System.Collections.Generic;
|
||
using System.Collections;
|
||
|
||
namespace PascalABCCompiler.TreeConverter
|
||
{
|
||
|
||
public enum block_type {function_block,type_block,namespace_block,compiled_type_block, lambda_block}; //lroman//
|
||
|
||
public class ContextState
|
||
{
|
||
// Stack<global::SymbolTable.Scope> _scope_stack; не трогать - работать с ним аккуратно при переходе в другой Scope
|
||
|
||
public common_namespace_node cmn; // текущий namespace
|
||
public common_type_node ctn; // текущий разбираемый тип
|
||
public common_function_node_stack func_stack;
|
||
public lambda_stack lambda_stack;
|
||
public Stack<code_block> block_stack;
|
||
public Dictionary<int, short_string_type_node> ShortStringTypes;
|
||
public List<var_definition_node> var_defs;
|
||
public Stack<List<var_definition_node>> var_defs_stack;
|
||
public List<local_variable> special_local_vars;
|
||
public List<type_instance_and_location> possible_incorrect_instances;
|
||
public bool skip_check_where_sections;
|
||
public statement_node main_procedure;
|
||
public bool allow_inherited_ctor_call;
|
||
public bool is_order_independed_method_description;
|
||
public template_class ctt;
|
||
public compiled_type_node compiled_tn;
|
||
public SymbolInfo last_created_function;
|
||
public statement_node_stack cycles_stack;
|
||
public int num_of_for_cycles;
|
||
public SemanticTree.field_access_level _fal;
|
||
public System.Collections.Hashtable member_decls;
|
||
public List<common_type_node> types_predefined;
|
||
public Stack<common_type_node> type_stack; // Для вложенных типов
|
||
public statement_list_stack stlist_stack;
|
||
public semantic_node ret_value; // Возвращаемое значение класса returner
|
||
public bool WithSection;
|
||
public Dictionary<SymbolTable.Scope, expression_node> WithVariables;
|
||
public Stack<SymbolTable.Scope> WithTypes;
|
||
//LambdaHelper.Reset(); // Пока не знаю, что с этим делать
|
||
|
||
}
|
||
|
||
public class compilation_context
|
||
{
|
||
private ContextState SavedContext = null; // сохраненный контекст, используется при переходе к другому контексту при компиляции и последующем возврате к первоначальному контексту
|
||
public Stack<ContextState> SavedContextStack = new Stack<ContextState>(); // SSM 26/08/15 - пробую сделать стек контекстов. Может, что-то надо будет клонировать?
|
||
|
||
// Существуют 3 перехода вверх:
|
||
// Из блока в раздел описаний до beginа этого блока (если это глобальный блок, то - на глобальный уровень). Обнуляется convertion_data_and_alghoritms.statement_list_stack. Поля func_stack и _ctn остаются нетронутыми
|
||
// Из блока в раздел описаний вне всех подпрограмм (если нет объемлющего класса, то это - глобальный уровень). Обнуляется func_stack, _ctn остаётся нетронутым
|
||
// Из любого блока на глобальный уровень. Обнуляется _ctn.
|
||
public void SaveContextAndUpToGlobalLevel()
|
||
{
|
||
if (!func_stack.Empty || SavedContext == null)
|
||
SaveContextAndUpFromAllFunctionDefs();
|
||
SavedContext.ctn = _ctn;
|
||
_ctn = null;
|
||
}
|
||
|
||
public void SaveContextAndUpFromAllFunctionDefs()
|
||
{
|
||
if (!convertion_data_and_alghoritms.statement_list_stack.Empty || SavedContext == null)
|
||
SaveContextAndUpToNearestDefSect();
|
||
SavedContext.func_stack = func_stack;
|
||
func_stack = new common_function_node_stack();
|
||
}
|
||
|
||
public void SaveContextAndUpToNearestDefSect()
|
||
{
|
||
// _scope_stack вообще не трогать - он не используется !!!!!
|
||
SavedContext = new ContextState();
|
||
SavedContext.stlist_stack = convertion_data_and_alghoritms.statement_list_stack;
|
||
SavedContext.cmn = _cmn;
|
||
SavedContext.ctn = _ctn;
|
||
SavedContext.func_stack = func_stack;
|
||
SavedContext.block_stack = block_stack;
|
||
SavedContext.ShortStringTypes = ShortStringTypes;
|
||
SavedContext.var_defs = var_defs;
|
||
SavedContext.var_defs_stack = var_defs_stack;
|
||
SavedContext.special_local_vars = _special_local_vars;
|
||
SavedContext.possible_incorrect_instances = possible_incorrect_instances;
|
||
SavedContext.skip_check_where_sections = skip_check_where_sections;
|
||
SavedContext.main_procedure = main_procedure;
|
||
SavedContext.allow_inherited_ctor_call = allow_inherited_ctor_call;
|
||
SavedContext.is_order_independed_method_description = is_order_independed_method_description;
|
||
SavedContext.ctt = _ctt;
|
||
SavedContext.compiled_tn = _compiled_tn;
|
||
SavedContext.last_created_function = last_created_function;
|
||
SavedContext.cycles_stack = _cycles_stack;
|
||
//SavedContext.num_of_for_cycles = num_of_for_cycles; // num_of_for_cycles вычисляется и провоцирует ошибки!
|
||
SavedContext._fal = _fal;
|
||
SavedContext.member_decls = member_decls;
|
||
SavedContext.types_predefined = _types_predefined;
|
||
SavedContext.ret_value = syntax_tree_visitor.ret.get_result();
|
||
SavedContext.WithTypes = WithTypes;
|
||
SavedContext.WithSection = WithSection;
|
||
SavedContext.WithVariables = WithVariables;
|
||
|
||
SavedContextStack.Push(SavedContext);
|
||
// SavedContext.type_stack = type_stack;
|
||
|
||
convertion_data_and_alghoritms.statement_list_stack = new statement_list_stack();
|
||
//_cmn = null;
|
||
//_ctn = null;
|
||
//func_stack = new common_function_node_stack();
|
||
//block_stack = new Stack<code_block>();
|
||
ShortStringTypes = new Dictionary<int,short_string_type_node>();
|
||
//var_defs = new List<var_definition_node>();
|
||
//var_defs_stack = new Stack<List<var_definition_node>>();
|
||
_special_local_vars = new List<local_variable>();
|
||
possible_incorrect_instances = new List<type_instance_and_location>();
|
||
skip_check_where_sections = false;
|
||
main_procedure = null;
|
||
allow_inherited_ctor_call = false;
|
||
is_order_independed_method_description = false;
|
||
_ctt = null;
|
||
_compiled_tn = null;
|
||
last_created_function = null;
|
||
_cycles_stack = new statement_node_stack();
|
||
_num_of_for_cycles = 0;
|
||
_fal = SemanticTree.field_access_level.fal_private;
|
||
member_decls = new Hashtable();
|
||
_types_predefined = new List<common_type_node>();
|
||
syntax_tree_visitor.ret.return_value(null);
|
||
// _type_stack = new Stack<common_type_node>();
|
||
|
||
}
|
||
|
||
public void RestoreCurrentContext()
|
||
{
|
||
SavedContext = SavedContextStack.Pop();
|
||
convertion_data_and_alghoritms.statement_list_stack = SavedContext.stlist_stack;
|
||
_cmn = SavedContext.cmn;
|
||
_ctn = SavedContext.ctn;
|
||
func_stack = SavedContext.func_stack;
|
||
block_stack = SavedContext.block_stack;
|
||
ShortStringTypes = SavedContext.ShortStringTypes;
|
||
var_defs = SavedContext.var_defs;
|
||
var_defs_stack = SavedContext.var_defs_stack;
|
||
_special_local_vars = SavedContext.special_local_vars;
|
||
possible_incorrect_instances = SavedContext.possible_incorrect_instances;
|
||
skip_check_where_sections = SavedContext.skip_check_where_sections;
|
||
main_procedure = SavedContext.main_procedure;
|
||
allow_inherited_ctor_call = SavedContext.allow_inherited_ctor_call;
|
||
is_order_independed_method_description = SavedContext.is_order_independed_method_description;
|
||
_ctt = SavedContext.ctt;
|
||
_compiled_tn = SavedContext.compiled_tn;
|
||
last_created_function = SavedContext.last_created_function;
|
||
_cycles_stack = SavedContext.cycles_stack;
|
||
//_num_of_for_cycles = SavedContext.num_of_for_cycles; // ssm 31/12/17 отключил! num_of_for_cycles вычисляется и провоцирует ошибки!
|
||
_fal = SavedContext._fal;
|
||
member_decls = SavedContext.member_decls;
|
||
_types_predefined = SavedContext.types_predefined;
|
||
WithTypes = SavedContext.WithTypes;
|
||
WithVariables = SavedContext.WithVariables;
|
||
WithSection = SavedContext.WithSection;
|
||
syntax_tree_visitor.ret.return_value(SavedContext.ret_value);
|
||
|
||
if (SavedContextStack.Count == 0)
|
||
SavedContext = null;
|
||
// type_stack = cs.type_stack; оно почему-то readonly - ну и ладно
|
||
}
|
||
|
||
public common_namespace_node _cmn;
|
||
//TODO: Можно сделать возможность объявления вложенных типов.
|
||
public common_type_node _ctn; // SSM - пытаюсь выходить из класса и входить заново
|
||
private common_function_node_stack _func_stack=new common_function_node_stack();
|
||
private type_node _explicit_interface_type;
|
||
internal bool WithSection = false;
|
||
internal Dictionary<SymbolTable.Scope, expression_node> WithVariables = new Dictionary<SymbolTable.Scope, expression_node>();
|
||
internal Stack<SymbolTable.Scope> WithTypes = new Stack<SymbolTable.Scope>();
|
||
|
||
internal common_function_node_stack func_stack
|
||
{
|
||
get
|
||
{
|
||
return _func_stack;
|
||
}
|
||
set
|
||
{
|
||
_func_stack = value;
|
||
}
|
||
}
|
||
|
||
|
||
private Stack<code_block> _block_stack = new Stack<code_block>();
|
||
|
||
internal Dictionary<type_node, common_type_node> TypedFiles = new Dictionary<type_node, common_type_node>();
|
||
internal Dictionary<type_node, common_type_node> TypedSets = new Dictionary<type_node, common_type_node>();
|
||
internal Dictionary<int, short_string_type_node> ShortStringTypes = new Dictionary<int, short_string_type_node>();
|
||
|
||
internal List<var_definition_node> var_defs =
|
||
new List<var_definition_node>();
|
||
|
||
internal Stack<System.Collections.Generic.List<var_definition_node>> var_defs_stack =
|
||
new Stack<System.Collections.Generic.List<var_definition_node>>();
|
||
|
||
internal List<local_variable> _special_local_vars =
|
||
new List<local_variable>();
|
||
|
||
internal Stack<SymbolTable.Scope> _scope_stack
|
||
= new Stack<SymbolTable.Scope>();
|
||
|
||
internal List<type_instance_and_location> possible_incorrect_instances = new List<type_instance_and_location>();
|
||
internal bool skip_check_where_sections = false;
|
||
|
||
private statement_node _main_procedure;
|
||
internal bool extension_method = false;
|
||
|
||
public bool allow_inherited_ctor_call = false;
|
||
public bool is_order_independed_method_description = false;
|
||
internal bool in_parameters_block = false;
|
||
|
||
private template_class _ctt = null;
|
||
|
||
private compiled_type_node _compiled_tn = null;
|
||
|
||
private SymbolInfo _last_created_function;
|
||
|
||
private statement_node_stack _cycles_stack=new statement_node_stack();
|
||
|
||
public statement_node_stack CyclesStack
|
||
{
|
||
get
|
||
{
|
||
return _cycles_stack;
|
||
}
|
||
set
|
||
{
|
||
_cycles_stack = value;
|
||
}
|
||
}
|
||
|
||
private int _num_for_delegates;
|
||
private int _num_of_for_cycles;
|
||
|
||
internal convertion_data_and_alghoritms convertion_data_and_alghoritms;
|
||
|
||
private SemanticTree.field_access_level _fal;
|
||
private bool _has_nested_functions;
|
||
internal syntax_tree_visitor syntax_tree_visitor { get; set; }
|
||
|
||
private static compilation_context _instance;
|
||
|
||
private Dictionary<common_namespace_node, Dictionary<string, template_class>> compiled_tc_cache = new Dictionary<common_namespace_node, Dictionary<string, template_class>>();
|
||
internal System.Collections.Hashtable member_decls = new System.Collections.Hashtable();
|
||
internal bool namespace_converted = false;
|
||
|
||
public compilation_context(convertion_data_and_alghoritms convertion_data_and_alghoritms, syntax_tree_visitor syntax_tree_visitor)
|
||
{
|
||
this.convertion_data_and_alghoritms = convertion_data_and_alghoritms;
|
||
this.syntax_tree_visitor = syntax_tree_visitor;
|
||
_instance = this;
|
||
}
|
||
|
||
|
||
public static compilation_context instance
|
||
{
|
||
get
|
||
{
|
||
return _instance;
|
||
}
|
||
}
|
||
|
||
internal void AddError(Errors.Error err)
|
||
{
|
||
syntax_tree_visitor.AddError(err);
|
||
}
|
||
|
||
internal void AddError(location loc, string ErrString, params string[] values)
|
||
{
|
||
syntax_tree_visitor.AddError(loc, ErrString, values);
|
||
}
|
||
|
||
internal bool can_call_inherited_ctor_call(statements_list lst)
|
||
{
|
||
if (lst.statements.Count == 0)
|
||
return true;
|
||
if (lst.statements[0] is basic_function_call)
|
||
{
|
||
base_function_call bfc = lst.statements[0] as basic_function_call;
|
||
if (bfc.type != null && bfc.type.name.Contains("<>local_variables_class"))
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
public void reset()
|
||
{
|
||
//CurrentHandlerList = null; // SSM 29/03/22 - не сработало
|
||
//CurrentHandlerListStack = new Stack<List<string>>(); // SSM 29/03/22 - не сработало
|
||
_cmn = null;
|
||
_ctn = null;
|
||
_func_stack.clear();
|
||
var_defs.Clear();
|
||
_main_procedure = null;
|
||
_last_created_function = null;
|
||
_cycles_stack.clear();
|
||
_num_of_for_cycles = 0;
|
||
_fal = SemanticTree.field_access_level.fal_private;
|
||
_num_for_delegates = 0;
|
||
rec_num = 1;
|
||
var_defs_stack.Clear();
|
||
type_stack.Clear();
|
||
clear_special_local_vars();
|
||
_scope_stack.Clear();
|
||
TypedFiles.Clear();
|
||
ShortStringTypes.Clear();
|
||
TypedSets.Clear();
|
||
_compiled_tn = null;
|
||
_explicit_interface_type = null;
|
||
_ctt = null;
|
||
allow_inherited_ctor_call = false;
|
||
_types_predefined.Clear();
|
||
_block_stack.Clear();
|
||
member_decls.Clear();
|
||
possible_incorrect_instances.Clear();
|
||
skip_check_where_sections = false;
|
||
LambdaHelper.Reset(); //lroman//
|
||
SavedContext = null;
|
||
SavedContextStack.Clear();
|
||
compiled_tc_cache.Clear();
|
||
extension_method = false;
|
||
_last_created_function = null;
|
||
in_parameters_block = false;
|
||
is_order_independed_method_description = false;
|
||
_has_nested_functions = false;
|
||
finally_blocks_depth = 0;
|
||
static_variable_converted = false;
|
||
}
|
||
|
||
public void clear_type_prededinitions()
|
||
{
|
||
_types_predefined.Clear();
|
||
}
|
||
|
||
public bool static_variable_converted;
|
||
|
||
public bool inStaticArea()
|
||
{
|
||
if (converted_type != null && top_function != null)
|
||
{
|
||
common_method_node cmn = top_function as common_method_node;
|
||
if (cmn == null)
|
||
{
|
||
common_in_function_function_node fn = top_function as common_in_function_function_node;
|
||
while (fn != null)
|
||
{
|
||
cmn = fn.function as common_method_node;
|
||
if(cmn!=null) break;
|
||
fn = fn.function as common_in_function_function_node;
|
||
}
|
||
}
|
||
if (cmn != null)
|
||
return cmn.IsStatic;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
public SymbolTable.Scope CurrentScope
|
||
{
|
||
get
|
||
{
|
||
if (!syntax_tree_visitor.convertion_data_and_alghoritms.statement_list_stack.Empty)
|
||
{
|
||
SymbolTable.Scope sc = syntax_tree_visitor.convertion_data_and_alghoritms.statement_list_stack.top().Scope;
|
||
if (sc != null)
|
||
{
|
||
if (top_function != null && LambdaHelper.IsLambdaName(top_function.name)) //lroman
|
||
{
|
||
var top_lambda_scope = top_function.scope.TopScope;
|
||
|
||
if (top_lambda_scope == sc)
|
||
{
|
||
return top_function.scope;
|
||
}
|
||
}
|
||
return sc;
|
||
}
|
||
}
|
||
if (top_function != null && LambdaHelper.IsLambdaName(top_function.name)) //lroman
|
||
{
|
||
return top_function.scope;
|
||
}
|
||
switch (converting_block())
|
||
{
|
||
case block_type.function_block:
|
||
{
|
||
return top_function.scope;
|
||
}
|
||
case block_type.namespace_block:
|
||
{
|
||
return converted_namespace.scope;
|
||
}
|
||
case block_type.type_block:
|
||
{
|
||
return converted_type.scope;
|
||
}
|
||
case block_type.compiled_type_block:
|
||
{
|
||
return converted_compiled_type.scope;
|
||
}
|
||
default:
|
||
{
|
||
throw new CompilerInternalError("Invalid converting block type");
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
public void push_function(common_function_node fn)
|
||
{
|
||
_func_stack.push(fn);
|
||
}
|
||
|
||
public common_function_node get_method_to_realize(SyntaxTree.declaration dc)
|
||
{
|
||
return member_decls[dc] as common_function_node;
|
||
}
|
||
|
||
public common_type_node get_type_to_realize(SyntaxTree.declaration dc)
|
||
{
|
||
return member_decls[dc] as common_type_node;
|
||
}
|
||
|
||
public void add_method_header(SyntaxTree.declaration dc, definition_node dn)
|
||
{
|
||
member_decls.Add(dc,dn);
|
||
}
|
||
|
||
public void add_type_header(SyntaxTree.type_declaration td, common_type_node ctn)
|
||
{
|
||
member_decls.Add(td, ctn);
|
||
}
|
||
|
||
public void clear_member_bindings()
|
||
{
|
||
if (!namespace_converted)
|
||
member_decls.Clear();
|
||
}
|
||
|
||
public void BeginSkipGenericInstanceChecking()
|
||
{
|
||
skip_check_where_sections = true;
|
||
}
|
||
|
||
public void EndSkipGenericInstanceChecking()
|
||
{
|
||
skip_check_where_sections = false;
|
||
generic_convertions.check_instances_are_correct(possible_incorrect_instances);
|
||
possible_incorrect_instances.Clear();
|
||
}
|
||
|
||
public void AddTemplate(string name, template_class tc, location loc)
|
||
{
|
||
//check_name_free(name, loc);
|
||
_cmn.scope.AddSymbol(name, new SymbolInfo(tc));
|
||
_cmn.templates.AddElement(tc);
|
||
}
|
||
|
||
public static common_type_node AddTypeToTypedFileList(common_type_node tctn)
|
||
{
|
||
if (instance.TypedFiles.ContainsKey(tctn.element_type)) return instance.TypedFiles[tctn.element_type];
|
||
instance.TypedFiles.Add(tctn.element_type,tctn);
|
||
return tctn;
|
||
}
|
||
|
||
public static common_type_node AddTypeToSetTypeList(common_type_node tctn)
|
||
{
|
||
if (instance.TypedSets.ContainsKey(tctn.element_type)) return instance.TypedSets[tctn.element_type];
|
||
instance.TypedSets.Add(tctn.element_type,tctn);
|
||
tctn.add_name(StringConstants.assign_name,new SymbolInfo(SystemLibrary.SystemLibrary.make_assign_operator(tctn,PascalABCCompiler.SemanticTree.basic_function_type.objassign)));
|
||
tctn.scope.AddSymbol(StringConstants.plus_name, SystemLibrary.SystemLibInitializer.SetUnionProcedure.SymbolInfo.FirstOrDefault());
|
||
tctn.scope.AddSymbol(StringConstants.mul_name, SystemLibrary.SystemLibInitializer.SetIntersectProcedure.SymbolInfo.FirstOrDefault());
|
||
tctn.scope.AddSymbol(StringConstants.in_name, SystemLibrary.SystemLibInitializer.InSetProcedure.SymbolInfo.FirstOrDefault());
|
||
tctn.scope.AddSymbol(StringConstants.minus_name, SystemLibrary.SystemLibInitializer.SetSubtractProcedure.SymbolInfo.FirstOrDefault());
|
||
tctn.scope.AddSymbol(StringConstants.eq_name, SystemLibrary.SystemLibInitializer.CompareSetEquals.SymbolInfo.FirstOrDefault());
|
||
tctn.scope.AddSymbol(StringConstants.noteq_name, SystemLibrary.SystemLibInitializer.CompareSetInEquals.SymbolInfo.FirstOrDefault());
|
||
tctn.scope.AddSymbol(StringConstants.sm_name, SystemLibrary.SystemLibInitializer.CompareSetLess.SymbolInfo.FirstOrDefault());
|
||
tctn.scope.AddSymbol(StringConstants.smeq_name, SystemLibrary.SystemLibInitializer.CompareSetLessEqual.SymbolInfo.FirstOrDefault());
|
||
tctn.scope.AddSymbol(StringConstants.gr_name, SystemLibrary.SystemLibInitializer.CompareSetGreater.SymbolInfo.FirstOrDefault());
|
||
tctn.scope.AddSymbol(StringConstants.greq_name, SystemLibrary.SystemLibInitializer.CompareSetGreaterEqual.SymbolInfo.FirstOrDefault());
|
||
tctn.scope.AddSymbol(StringConstants.plusassign_name,new SymbolInfo(make_set_plus_assign(tctn)));
|
||
tctn.scope.AddSymbol(StringConstants.minusassign_name,new SymbolInfo(make_set_minus_assign(tctn)));
|
||
tctn.scope.AddSymbol(StringConstants.multassign_name,new SymbolInfo(make_set_mult_assign(tctn)));
|
||
return tctn;
|
||
}
|
||
|
||
public static void AddTypeToShortStringTypeList(type_node tn)
|
||
{
|
||
instance.ShortStringTypes.Add((tn as short_string_type_node).Length,tn as short_string_type_node);
|
||
tn.add_name(StringConstants.plus_name,new SymbolInfo(SystemLibrary.SystemLibrary.string_add));
|
||
}
|
||
|
||
public void pop_top_function()
|
||
{
|
||
_func_stack.pop();
|
||
}
|
||
|
||
private List<common_type_node> _types_predefined = new List<common_type_node>();
|
||
public List<common_type_node> types_predefined
|
||
{
|
||
get
|
||
{
|
||
return _types_predefined;
|
||
}
|
||
}
|
||
|
||
public Stack<code_block> block_stack
|
||
{
|
||
get { return _block_stack; }
|
||
set { _block_stack = value; }
|
||
}
|
||
|
||
public void AddTemplateInstance(string name, type_node t)
|
||
{
|
||
_cmn.scope.AddSymbol(name, new SymbolInfo(t));
|
||
}
|
||
|
||
private void clear_special_local_vars()
|
||
{
|
||
_special_local_vars.Clear();
|
||
}
|
||
|
||
public void add_special_local_var(local_variable lv)
|
||
{
|
||
_special_local_vars.Add(lv);
|
||
}
|
||
|
||
public void apply_special_local_vars(common_namespace_function_node cnfn)
|
||
{
|
||
foreach (local_variable lv in _special_local_vars)
|
||
{
|
||
lv.function = cnfn;
|
||
cnfn.var_definition_nodes_list.AddElement(lv);
|
||
}
|
||
clear_special_local_vars();
|
||
}
|
||
|
||
public void enter_scope(global::SymbolTable.Scope new_scope)
|
||
{
|
||
switch (converting_block())
|
||
{
|
||
case block_type.function_block:
|
||
{
|
||
_scope_stack.Push(top_function.scope);
|
||
top_function.scope = new_scope;
|
||
break;
|
||
}
|
||
case block_type.namespace_block:
|
||
{
|
||
_scope_stack.Push(_cmn.scope);
|
||
_cmn.scope = new_scope;
|
||
break;
|
||
}
|
||
case block_type.type_block:
|
||
{
|
||
throw new CompilerInternalError("Unsupported scope relations");
|
||
}
|
||
default:
|
||
{
|
||
throw new CompilerInternalError("Undefined block type");
|
||
}
|
||
}
|
||
}
|
||
|
||
/*private List<global::SymbolTable.Scope> with_stack = new List<global::SymbolTable.Scope>();
|
||
private List<expression_node> with_expr_stack = new List<expression_node>();
|
||
|
||
public void enter_scope(global::SymbolTable.Scope new_scope, expression_node en)
|
||
{
|
||
with_stack.Add(new_scope);
|
||
with_expr_stack.Add(en);
|
||
}*/
|
||
|
||
public void leave_scope()
|
||
{
|
||
switch (converting_block())
|
||
{
|
||
case block_type.function_block:
|
||
{
|
||
top_function.scope = _scope_stack.Pop();
|
||
break;
|
||
}
|
||
case block_type.namespace_block:
|
||
{
|
||
_cmn.scope = _scope_stack.Pop();
|
||
break;
|
||
}
|
||
case block_type.type_block:
|
||
{
|
||
throw new CompilerInternalError("Unsupported scope relations");
|
||
break;
|
||
}
|
||
default:
|
||
{
|
||
throw new CompilerInternalError("Undefined block type");
|
||
}
|
||
}
|
||
}
|
||
|
||
public statement_node main_procedure
|
||
{
|
||
get
|
||
{
|
||
return _main_procedure;
|
||
}
|
||
set
|
||
{
|
||
_main_procedure=value;
|
||
}
|
||
}
|
||
|
||
public void set_field_access_level(SemanticTree.field_access_level fal)
|
||
{
|
||
_fal=fal;
|
||
}
|
||
|
||
public SemanticTree.field_access_level get_field_access_level()
|
||
{
|
||
return _fal;
|
||
}
|
||
|
||
public common_function_node top_function
|
||
{
|
||
get
|
||
{
|
||
if (_func_stack.size==0)
|
||
{
|
||
return null;
|
||
}
|
||
return (_func_stack.top());
|
||
}
|
||
}
|
||
|
||
public type_node converted_explicit_interface_type
|
||
{
|
||
get
|
||
{
|
||
return _explicit_interface_type;
|
||
}
|
||
//ssyy
|
||
set
|
||
{
|
||
_explicit_interface_type = value;
|
||
}
|
||
//\ssyy
|
||
}
|
||
|
||
public common_type_node converted_type
|
||
{
|
||
get
|
||
{
|
||
return _ctn;
|
||
}
|
||
//ssyy
|
||
set
|
||
{
|
||
_ctn = value;
|
||
}
|
||
//\ssyy
|
||
}
|
||
|
||
public bool has_nested_functions
|
||
{
|
||
get
|
||
{
|
||
return _has_nested_functions;
|
||
}
|
||
set
|
||
{
|
||
_has_nested_functions = value;
|
||
}
|
||
}
|
||
|
||
//ssyy
|
||
public common_function_node_stack converted_func_stack
|
||
{
|
||
get
|
||
{
|
||
return _func_stack;
|
||
}
|
||
set
|
||
{
|
||
_func_stack = value;
|
||
}
|
||
}
|
||
|
||
public template_class converted_template_type
|
||
{
|
||
get
|
||
{
|
||
return _ctt;
|
||
}
|
||
set
|
||
{
|
||
_ctt = value;
|
||
}
|
||
}
|
||
//\ssyy
|
||
|
||
public compiled_type_node converted_compiled_type
|
||
{
|
||
get
|
||
{
|
||
return _compiled_tn;
|
||
}
|
||
set
|
||
{
|
||
_compiled_tn = value;
|
||
}
|
||
}
|
||
|
||
public common_namespace_node converted_namespace
|
||
{
|
||
get
|
||
{
|
||
return _cmn;
|
||
}
|
||
set
|
||
{
|
||
_cmn = value;
|
||
}
|
||
}
|
||
|
||
public common_namespace_node create_namespace(common_namespace_node comprehensive_namespace,string namespace_name,
|
||
common_unit_node cont_unit,SymbolTable.Scope _scope,location loc)
|
||
{
|
||
SymbolTable.Scope scope;
|
||
if (comprehensive_namespace == null)
|
||
{
|
||
//scope = convertion_data_and_alghoritms.symbol_table.CreateScope(cont_unit.scope);
|
||
scope = _scope;
|
||
}
|
||
else
|
||
{
|
||
scope = convertion_data_and_alghoritms.symbol_table.CreateScope(comprehensive_namespace.scope, "namespace " + namespace_name);
|
||
}
|
||
_cmn = new common_namespace_node(comprehensive_namespace, cont_unit, namespace_name, scope, loc);
|
||
cont_unit.namespaces.AddElement(_cmn);
|
||
_cmn.scope.AddSymbol(namespace_name,new SymbolInfo(_cmn));
|
||
return _cmn;
|
||
}
|
||
|
||
public common_namespace_node create_namespace(string namespace_name, common_unit_node cont_unit,SymbolTable.Scope _scope, location loc)
|
||
{
|
||
return create_namespace(null, namespace_name, cont_unit,_scope, loc);
|
||
}
|
||
|
||
public bool func_stack_size_is_one()
|
||
{
|
||
return (_func_stack.size == 1);
|
||
}
|
||
|
||
public block_type converting_block()
|
||
{
|
||
//if (_ctn != null && _ctn.is_value_type) return block_type.type_block;
|
||
//if (with_stack.Count > 0) return block_type.with_block;
|
||
if (_ctn != null && top_function!=null && _ctn.defined_in_scope == top_function.scope)
|
||
return block_type.type_block;
|
||
|
||
if (_func_stack.size!=0)
|
||
{
|
||
return block_type.function_block;
|
||
}
|
||
if (_ctn!=null)
|
||
{
|
||
return block_type.type_block;
|
||
}
|
||
if (_compiled_tn != null)
|
||
return block_type.compiled_type_block;
|
||
return block_type.namespace_block;
|
||
}
|
||
|
||
internal bool IsCompiledType(string type_name)
|
||
{
|
||
SymbolInfo si = find_first(type_name);
|
||
if (si == null)
|
||
return false;
|
||
return si.sym_info is compiled_type_node;
|
||
}
|
||
|
||
public definition_node check_name_node_type(string name, location loc, params general_node_type[] expected_node_types) // SSM перебросил сюда из syntax_tree_visitor 3.04.14
|
||
{
|
||
SymbolInfo si = find_first(name);
|
||
return check_name_node_type(name, si, loc, expected_node_types);
|
||
}
|
||
public definition_node check_name_node_type(string name, SymbolInfo si, location loc, params general_node_type[] expected_node_types) // SSM перебросил сюда из syntax_tree_visitor 3.04.14
|
||
{
|
||
if (si == null)
|
||
{
|
||
AddError(new UndefinedNameReference(name, loc));
|
||
return null;
|
||
}
|
||
|
||
int i = 0;
|
||
if (si.sym_info == null)
|
||
{
|
||
if (name.Equals(StringConstants.result_var_name, CurrentScope.StringComparison))
|
||
AddError(loc, "CAN_NOT_DEDUCE_TYPE_{0}", StringConstants.result_var_name);
|
||
else
|
||
AddError(new ExpectedType(loc));
|
||
}
|
||
|
||
if (si.sym_info.semantic_node_type == semantic_node_type.wrap_def)
|
||
{
|
||
BasePCUReader.RestoreSymbol(si, name);
|
||
}
|
||
while (i < expected_node_types.Length)
|
||
{
|
||
if (si.sym_info.general_node_type == expected_node_types[i])
|
||
{
|
||
break;
|
||
}
|
||
i++;
|
||
}
|
||
if (i >= expected_node_types.Length)
|
||
{
|
||
if (expected_node_types.Length == 1)
|
||
if (expected_node_types[0] == general_node_type.type_node)
|
||
AddError(new ExpectedType(loc));
|
||
AddError(new ExpectedAnotherKindOfObject(expected_node_types, si.sym_info.general_node_type,
|
||
convertion_data_and_alghoritms.get_location(si.sym_info), loc));
|
||
}
|
||
|
||
//if (SystemUnitAssigned && SystemLibrary.SystemLibInitializer.ShortStringType.Found && SystemLibrary.SystemLibInitializer.ShortStringType.Equal(si))
|
||
// return context.create_short_string_type(SemanticRules.ShortStringDefaultLength, loc);
|
||
|
||
return si.sym_info;
|
||
}
|
||
|
||
//ssyy
|
||
//Определение предпоследнего имени - как имени модуля
|
||
private definition_node convert_names_to_namespace(SyntaxTree.named_type_reference names, location loc) // SSM перебросил сюда из syntax_tree_visitor 3.04.14
|
||
{
|
||
//предполагается, что количество имён больше чем 1.
|
||
definition_node di = null;
|
||
location loc1 = syntax_tree_visitor.get_location(names.names[0]);
|
||
if (loc1 == null)
|
||
loc1 = loc;
|
||
di = check_name_node_type(names.names[0].name, loc1, general_node_type.namespace_node, general_node_type.unit_node, general_node_type.type_node);
|
||
for (int i = 1; i < names.names.Count - 1; i++)
|
||
{
|
||
List<SymbolInfo> sil = null;
|
||
if (di is common_unit_node)
|
||
{
|
||
sil = (di as common_unit_node).find_only_in_namespace(names.names[i].name); // SSM 23.04.24 fix #3086
|
||
}
|
||
else
|
||
if (di is namespace_node)
|
||
{
|
||
sil = (di as namespace_node).find(names.names[i].name);
|
||
}
|
||
else
|
||
sil = (di as type_node).find_in_type(names.names[i].name);
|
||
loc1 = syntax_tree_visitor.get_location(names.names[i]);
|
||
if (loc1 == null)
|
||
loc1 = loc;
|
||
di = check_name_node_type(names.names[i].name, sil?.FirstOrDefault(), loc1, general_node_type.namespace_node, general_node_type.type_node);
|
||
}
|
||
return di;
|
||
}
|
||
|
||
//Нахождение узла по имени либо точечному имени (напр. Unit1.type1)
|
||
public List<SymbolInfo> find_definition_node(SyntaxTree.named_type_reference names, location loc, bool throw_error = false) // SSM перебросил сюда из syntax_tree_visitor 3.04.14
|
||
{
|
||
definition_node di = null;
|
||
List<SymbolInfo> si = null;
|
||
if (names.names.Count > 1)
|
||
{
|
||
di = convert_names_to_namespace(names, loc);
|
||
}
|
||
if (di != null)
|
||
{
|
||
int num = names.names.Count - 1;
|
||
if (di is namespace_node)
|
||
{
|
||
si = (di as namespace_node).findOnlyInNamespace(names.names[num].name);
|
||
if (si == null && throw_error)
|
||
AddError(new UndefinedNameReference(names.names[num].name, syntax_tree_visitor.get_location(names.names[num])));
|
||
}
|
||
else if (di is type_node)
|
||
{
|
||
si = (di as type_node).find_in_type(names.names[num].name);
|
||
if (si == null && throw_error)
|
||
AddError(new UndefinedNameReference(names.names[num].name, syntax_tree_visitor.get_location(names.names[num])));
|
||
}
|
||
else
|
||
{
|
||
si = (di as unit_node).find_only_in_namespace(names.names[num].name);
|
||
if (si == null && throw_error)
|
||
AddError(new UndefinedNameReference(names.names[num].name, syntax_tree_visitor.get_location(names.names[num])));
|
||
}
|
||
return si;
|
||
}
|
||
si = find(names.names[0].name);
|
||
if (si == null && throw_error)
|
||
AddError(new UndefinedNameReference(names.names[0].name, syntax_tree_visitor.get_location(names.names[0])));
|
||
return si;
|
||
}
|
||
//\ssyy
|
||
|
||
//(ssyy) возвращаемое значение заменено на definition_node из-за шаблонов
|
||
public definition_node enter_in_type_method(SyntaxTree.method_name meth_name, string type_name, location loc, int num_template_args)
|
||
{
|
||
// num_template_args - это количество обобщенных аргументов в классе (не в методе!)
|
||
List<SymbolInfo> sil = null;
|
||
|
||
if (meth_name.ln!=null && meth_name.ln.Count > 1)
|
||
{
|
||
// обработать эту ситуацию особо тщательно: в ln - список возможных пространств имен с классом (возможно, обобщенным) на конце
|
||
|
||
// если в ln какое-то имя кроме последнего, содержит обобщенные параметры - это ошибка
|
||
for (var i = 0; i < meth_name.ln.Count - 1; i++)
|
||
if (meth_name.ln[i] is SyntaxTree.template_type_name)
|
||
AddError(new NameCannotHaveGenericParameters(meth_name.ln[i].name, syntax_tree_visitor.get_location(meth_name.ln[i])));
|
||
|
||
var ntr = new SyntaxTree.named_type_reference();
|
||
for (var i = 0; i < meth_name.ln.Count; i++)
|
||
ntr.Add(meth_name.ln[i]);
|
||
if (num_template_args>0 && ! ntr.names[meth_name.ln.Count-1].name.Contains(StringConstants.generic_params_infix))
|
||
{
|
||
ntr.names[meth_name.ln.Count-1].name += StringConstants.generic_params_infix + num_template_args;
|
||
}
|
||
sil = find_definition_node(ntr, loc);
|
||
// если не нашли, то ошибка будет неправильной с неправильным именем - надо исправить
|
||
}
|
||
else
|
||
{
|
||
if (num_template_args != 0)
|
||
{
|
||
string template_type_name = type_name + StringConstants.generic_params_infix + num_template_args.ToString();
|
||
sil = find(template_type_name);
|
||
/*if (si == null || si.sym_info.general_node_type != general_node_type.template_type)
|
||
{
|
||
type_name = type_name + StringConstants.generic_params_infix + num_template_args.ToString();
|
||
si = null;
|
||
}*/
|
||
}
|
||
if (sil == null)
|
||
{
|
||
sil = find(type_name);
|
||
}
|
||
}
|
||
|
||
if (sil == null)
|
||
{
|
||
AddError(new UndefinedNameReference(type_name, loc));
|
||
}
|
||
definition_node dn = sil.FirstOrDefault().sym_info;
|
||
if (dn.general_node_type == general_node_type.template_type)
|
||
{
|
||
_ctt = dn as template_class;
|
||
if (_cmn != _ctt.cnn && _ctt.using_list2 == null)
|
||
{
|
||
//Заполняем список using для внешних методов
|
||
_ctt.using_list2 = new using_namespace_list();
|
||
foreach(using_namespace un in syntax_tree_visitor.using_list)
|
||
{
|
||
_ctt.using_list2.AddElement(un);
|
||
}
|
||
}
|
||
return dn;
|
||
}
|
||
if (dn.general_node_type == general_node_type.generic_indicator)
|
||
{
|
||
dn = (dn as generic_indicator).generic;
|
||
}
|
||
if (dn is compiled_type_node)
|
||
{
|
||
_compiled_tn = dn as compiled_type_node;
|
||
return dn;
|
||
}
|
||
if (dn.general_node_type != general_node_type.type_node)
|
||
{
|
||
AddError(loc, "TYPE_NAME_EXPECTED");
|
||
}
|
||
#if DEBUG
|
||
if (sil.Count() != 1)
|
||
{
|
||
throw new CompilerInternalError("Must find only type, found some other.");
|
||
}
|
||
#endif
|
||
if (dn.semantic_node_type != semantic_node_type.common_type_node)
|
||
{
|
||
AddError(loc, "ONLY_COMMON_TYPE_METHOD_DEFINITION_ALLOWED");
|
||
}
|
||
|
||
//TODO: В случае создания вложенных классов этот код надо поправить.
|
||
common_type_node ctn = dn as common_type_node;
|
||
_ctn = ctn;
|
||
return ctn;
|
||
}
|
||
|
||
public void leave_type_method()
|
||
{
|
||
if (_explicit_interface_type != null)
|
||
{
|
||
function_node fn = top_function;
|
||
List<SymbolInfo> sil = _ctn.Scope.FindOnlyInType(fn.name, null);
|
||
function_node compar;
|
||
if(sil != null)
|
||
foreach(var si in sil)
|
||
{
|
||
compar = si.sym_info as function_node;
|
||
if (fn != compar && convertion_data_and_alghoritms.function_eq_params(fn, compar))
|
||
if (fn is common_namespace_function_node && compar is common_namespace_function_node && (fn as common_namespace_function_node).comprehensive_namespace == (compar as common_namespace_function_node).comprehensive_namespace)
|
||
|
||
AddError(new FunctionDuplicateDefinition(compar, fn));
|
||
}
|
||
}
|
||
else if (_compiled_tn != null)
|
||
{
|
||
function_node fn = top_function;
|
||
List<SymbolInfo> sil = _compiled_tn.scope.FindOnlyInType(fn.name, null);
|
||
function_node compar;
|
||
if(sil != null)
|
||
foreach(var si in sil)
|
||
{
|
||
compar = si.sym_info as function_node;
|
||
if (fn!=compar && convertion_data_and_alghoritms.function_eq_params(fn, compar,false))
|
||
//if (fn is common_namespace_function_node && compar is common_namespace_function_node && (fn as common_namespace_function_node).comprehensive_namespace == (compar as common_namespace_function_node).comprehensive_namespace)
|
||
|
||
AddError(new FunctionDuplicateDefinition(compar, fn));
|
||
}
|
||
}
|
||
if (_explicit_interface_type == null)
|
||
_ctn = null;
|
||
_compiled_tn = null;
|
||
_explicit_interface_type = null;
|
||
}
|
||
|
||
private readonly System.Collections.Generic.Stack<common_type_node> type_stack = new System.Collections.Generic.Stack<common_type_node>();
|
||
|
||
internal void add_notequal_operator_if_need(bool not_add_body= false)
|
||
{
|
||
List<SymbolInfo> si_list = _ctn.find_in_type(StringConstants.noteq_name);
|
||
common_method_node cmn = null;
|
||
common_parameter prm1 = null;
|
||
common_parameter prm2 = null;
|
||
foreach (SymbolInfo si2 in si_list)
|
||
if (si2.sym_info is common_method_node)
|
||
{
|
||
cmn = si2.sym_info as common_method_node;
|
||
if (cmn.function_code != null && cmn.parameters.Count == 2 && cmn.parameters[0].type == cmn.parameters[1].type)
|
||
return;
|
||
}
|
||
if (cmn != null && cmn.function_code != null)
|
||
cmn = null;
|
||
SymbolInfo si = si_list[0];
|
||
SymbolTable.ClassMethodScope scope = convertion_data_and_alghoritms.symbol_table.CreateClassMethodScope(_ctn.scope, _cmn.scope, null, si.ToString());
|
||
if (cmn == null)
|
||
{
|
||
cmn = new common_method_node(StringConstants.GetNETOperName(StringConstants.noteq_name), SystemLibrary.SystemLibrary.bool_type, null, _ctn,
|
||
SemanticTree.polymorphic_state.ps_static, SemanticTree.field_access_level.fal_public, scope);
|
||
cmn.IsOperator = true;
|
||
prm1 = new common_parameter("a", _ctn, SemanticTree.parameter_type.value, cmn, concrete_parameter_type.cpt_none, null, null);
|
||
prm2 = new common_parameter("b", _ctn, SemanticTree.parameter_type.value, cmn, concrete_parameter_type.cpt_none, null, null);
|
||
cmn.parameters.AddElement(prm1);
|
||
cmn.parameters.AddElement(prm2);
|
||
cmn.is_overload = true;
|
||
_ctn.methods.AddElement(cmn);
|
||
_ctn.Scope.AddSymbol(StringConstants.noteq_name, new SymbolInfo(cmn));
|
||
}
|
||
else
|
||
{
|
||
prm1 = cmn.parameters[0] as common_parameter;
|
||
prm2 = cmn.parameters[1] as common_parameter;
|
||
}
|
||
if (not_add_body)
|
||
return;
|
||
statements_list body = new statements_list(null);
|
||
foreach (class_field cf in _ctn.fields)
|
||
{
|
||
if (cf.polymorphic_state == SemanticTree.polymorphic_state.ps_static)
|
||
continue;
|
||
expression_node left = new class_field_reference(cf,new common_parameter_reference(prm1,0,null),null);
|
||
expression_node right = new class_field_reference(cf,new common_parameter_reference(prm2,0,null),null);
|
||
expression_node cond = SystemLibrary.SystemLibrary.syn_visitor.find_operator(StringConstants.noteq_name,
|
||
left,right,null);
|
||
//basic_function_call bfc = new basic_function_call(SystemLibrary.SystemLibrary.bool_not as basic_function_node,null);
|
||
//bfc.parameters.AddElement(cond);
|
||
if_node if_stmt = new if_node(cond,new return_node(new bool_const_node(true,null),null),null,null);
|
||
body.statements.AddElement(if_stmt);
|
||
}
|
||
body.statements.AddElement(new return_node(new bool_const_node(false,null),null));
|
||
cmn.function_code = body;
|
||
|
||
}
|
||
|
||
internal void add_equal_operator_if_need(bool not_add_body=false)
|
||
{
|
||
List<SymbolInfo> si_list = _ctn.find_in_type(StringConstants.eq_name);
|
||
common_method_node cmn = null;
|
||
common_parameter prm1 = null;
|
||
common_parameter prm2 = null;
|
||
foreach (SymbolInfo si2 in si_list)
|
||
if (si2.sym_info is common_method_node)
|
||
{
|
||
cmn = si2.sym_info as common_method_node;
|
||
if (cmn.function_code != null && cmn.parameters.Count == 2 && cmn.parameters[0].type == cmn.parameters[1].type)
|
||
return;
|
||
}
|
||
if (cmn != null && cmn.function_code != null)
|
||
cmn = null;
|
||
SymbolInfo si = si_list[0];
|
||
SymbolTable.ClassMethodScope scope = convertion_data_and_alghoritms.symbol_table.CreateClassMethodScope( _ctn.scope, _cmn.scope, null, si.ToString());
|
||
if (cmn == null)
|
||
{
|
||
cmn = new common_method_node(StringConstants.GetNETOperName(StringConstants.eq_name), SystemLibrary.SystemLibrary.bool_type, null, _ctn,
|
||
SemanticTree.polymorphic_state.ps_static, SemanticTree.field_access_level.fal_public, scope);
|
||
cmn.IsOperator = true;
|
||
prm1 = new common_parameter("a", _ctn, SemanticTree.parameter_type.value, cmn, concrete_parameter_type.cpt_none, null, null);
|
||
prm2 = new common_parameter("b", _ctn, SemanticTree.parameter_type.value, cmn, concrete_parameter_type.cpt_none, null, null);
|
||
cmn.parameters.AddElement(prm1);
|
||
cmn.parameters.AddElement(prm2);
|
||
cmn.is_overload = true;
|
||
_ctn.methods.AddElement(cmn);
|
||
_ctn.Scope.AddSymbol(StringConstants.eq_name, new SymbolInfo(cmn));
|
||
}
|
||
else
|
||
{
|
||
prm1 = cmn.parameters[0] as common_parameter;
|
||
prm2 = cmn.parameters[1] as common_parameter;
|
||
}
|
||
if (not_add_body)
|
||
return;
|
||
statements_list body = new statements_list(null);
|
||
foreach (class_field cf in _ctn.fields)
|
||
{
|
||
if (cf.polymorphic_state == SemanticTree.polymorphic_state.ps_static)
|
||
continue;
|
||
expression_node left = new class_field_reference(cf,new common_parameter_reference(prm1,0,null),null);
|
||
expression_node right = new class_field_reference(cf,new common_parameter_reference(prm2,0,null),null);
|
||
expression_node cond = SystemLibrary.SystemLibrary.syn_visitor.find_operator(StringConstants.eq_name,
|
||
left,right,null);
|
||
basic_function_call bfc = new basic_function_call(SystemLibrary.SystemLibrary.bool_not as basic_function_node,null);
|
||
bfc.parameters.AddElement(cond);
|
||
if_node if_stmt = new if_node(bfc,new return_node(new bool_const_node(false,null),null),null,null);
|
||
body.statements.AddElement(if_stmt);
|
||
}
|
||
body.statements.AddElement(new return_node(new bool_const_node(true,null),null));
|
||
cmn.function_code = body;
|
||
|
||
}
|
||
|
||
public void leave_record()
|
||
{
|
||
check_implement_interfaces();
|
||
if (!_ctn.IsEnum)
|
||
{
|
||
//add_equal_operator_if_need();
|
||
//add_notequal_operator_if_need();
|
||
}
|
||
if (type_stack.Count != 0)
|
||
{
|
||
_cmn.types.AddElement(_ctn);
|
||
_ctn = type_stack.Pop();
|
||
}
|
||
else
|
||
{
|
||
_cmn.types.AddElement(_ctn);
|
||
_ctn = null;
|
||
}
|
||
}
|
||
|
||
public SymbolInfo create_special_names()
|
||
{
|
||
SymbolInfo si= new SymbolInfo(top_function.return_variable);
|
||
top_function.scope.AddSymbol(StringConstants.result_var_name, si);
|
||
return si;
|
||
}
|
||
|
||
public void create_lambda() //lroman//
|
||
{
|
||
SymbolTable.Scope scope = convertion_data_and_alghoritms.symbol_table.CreateLambdaScope(CurrentScope);
|
||
lambda_node new_lambda = new lambda_node(scope);
|
||
LambdaHelper.CurrentLambdaScopeNum = new_lambda.scope.ScopeNum;
|
||
}
|
||
|
||
public void remove_lambda_function(string lambda_name, bool remove_from_context) //lroman//
|
||
{
|
||
//На случай, если произошла ошибка при компиляции, то надо удалять из стека функций, так как не докомпилировали до конца, и ошибочная версия все еще в стеке
|
||
if (remove_from_context)
|
||
{
|
||
if (converting_block() == block_type.function_block)
|
||
{
|
||
var top_func = func_stack.top();
|
||
if (top_func.name == lambda_name)
|
||
{
|
||
_func_stack.pop();
|
||
}
|
||
}
|
||
}
|
||
|
||
if (LambdaHelper.StatementListStackStack.Count == 0)
|
||
{
|
||
return;
|
||
}
|
||
|
||
var top_statement_list_stack = LambdaHelper.StatementListStackStack.Peek();
|
||
|
||
if (top_statement_list_stack.Key != lambda_name)
|
||
{
|
||
return;
|
||
}
|
||
|
||
syntax_tree_visitor.convertion_data_and_alghoritms.statement_list_stack =
|
||
LambdaHelper.StatementListStackStack.Pop().Value;
|
||
}
|
||
|
||
public void remove_lambda() //lroman//
|
||
{
|
||
LambdaHelper.CurrentLambdaScopeNum = -1;
|
||
}
|
||
|
||
//lroman//
|
||
public common_function_node create_lambda_function(string name, location def_loc, bool add_symbol_info, SymbolTable.Scope topScope)
|
||
{
|
||
var func_stack_as_array = _func_stack.CloneInternalStack().ToList();
|
||
|
||
var nestedFunc = func_stack_as_array.FirstOrDefault(func => func is common_in_function_function_node);
|
||
if (nestedFunc != null)
|
||
{
|
||
syntax_tree_visitor.AddError(new LambdasAreNotAllowedInNestedSubprogram(def_loc));
|
||
}
|
||
|
||
LambdaHelper.StatementListStackStack.Push(new KeyValuePair<string, statement_list_stack>(name, syntax_tree_visitor.convertion_data_and_alghoritms.statement_list_stack));
|
||
syntax_tree_visitor.convertion_data_and_alghoritms.statement_list_stack = new statement_list_stack();
|
||
|
||
check_function_name(name, def_loc);
|
||
common_function_node cfn = null;
|
||
|
||
if (_ctn != null)
|
||
{
|
||
common_method_node cmmn;
|
||
|
||
// aab 26.04.19
|
||
// Здесь topScope записывается именно в CurrentLambdaDefScope, а не в DefScope
|
||
// Во всех остальных случаях записывается в DefScope
|
||
SymbolTable.Scope scope = convertion_data_and_alghoritms.symbol_table.CreateClassMethodScope(_ctn.Scope, null, topScope, "lambda " + name);
|
||
|
||
//TODO:сделать static и virtual.
|
||
//TODO: interface and implementation scopes.
|
||
cmmn = new common_method_node(name, def_loc, _ctn, SemanticTree.polymorphic_state.ps_common, _fal, scope);
|
||
|
||
_last_created_function = new SymbolInfo(cmmn);
|
||
if (add_symbol_info)
|
||
_ctn.Scope.AddSymbol(name, _last_created_function);
|
||
_ctn.methods.AddElement(cmmn);
|
||
|
||
cfn = cmmn;
|
||
}
|
||
else
|
||
{
|
||
common_namespace_function_node cnfnn;
|
||
SymbolTable.Scope scope = convertion_data_and_alghoritms.symbol_table.CreateScope(topScope, "lambda " + name);
|
||
cnfnn = new common_namespace_function_node(name, def_loc, _cmn, scope);
|
||
_cmn.functions.AddElement(cnfnn);
|
||
_last_created_function = new SymbolInfo(cnfnn);
|
||
if (add_symbol_info)
|
||
_cmn.scope.AddSymbol(name, _last_created_function);
|
||
cfn = cnfnn;
|
||
}
|
||
|
||
_func_stack.push(cfn);
|
||
return cfn;
|
||
}
|
||
//\lroman//
|
||
|
||
public common_function_node create_function(string name, location def_loc)
|
||
{
|
||
return create_function(name, def_loc, true);
|
||
}
|
||
public common_function_node create_function(string name,location def_loc, bool add_symbol_info)
|
||
{
|
||
if (converting_block() == block_type.compiled_type_block)
|
||
{
|
||
_compiled_tn = compiled_type_node.get_type_node(_compiled_tn.compiled_type,this.syntax_tree_visitor.SymbolTable);
|
||
}
|
||
check_function_name(name, def_loc);
|
||
common_function_node cfn = null;
|
||
switch (converting_block())
|
||
{
|
||
case block_type.function_block:
|
||
{
|
||
common_function_node top_func = _func_stack.top();
|
||
SymbolTable.Scope scope = convertion_data_and_alghoritms.symbol_table.CreateScope(top_func.scope, "function " + name);
|
||
common_in_function_function_node ciffn =new common_in_function_function_node(name,def_loc,top_func,scope);
|
||
top_func.functions_nodes_list.AddElement(ciffn);
|
||
_last_created_function = new SymbolInfo(ciffn);
|
||
if (add_symbol_info)
|
||
top_func.scope.AddSymbol(name, _last_created_function);
|
||
cfn=ciffn;
|
||
break;
|
||
}
|
||
case block_type.type_block:
|
||
{
|
||
if (!extension_method)
|
||
{
|
||
common_method_node cmmn;
|
||
SymbolTable.Scope scope = convertion_data_and_alghoritms.symbol_table.CreateClassMethodScope(_ctn.Scope, /*name.ToLower() == "create" ? _ctn.Scope :*/ _cmn.scope, null,
|
||
name == StringConstants.default_constructor_name ? "constructor " + _ctn.Scope : "method " + name);
|
||
//TODO:сделать static и virtual.
|
||
//TODO: interface and implementation scopes.
|
||
cmmn = new common_method_node(name, def_loc, _ctn, SemanticTree.polymorphic_state.ps_common, _fal, scope);
|
||
|
||
_last_created_function = new SymbolInfo(cmmn);
|
||
if (add_symbol_info)
|
||
_ctn.Scope.AddSymbol(name, _last_created_function);
|
||
_ctn.methods.AddElement(cmmn);
|
||
|
||
cfn = cmmn;
|
||
}
|
||
else
|
||
{
|
||
common_namespace_function_node cnfnn;
|
||
SymbolTable.Scope scope = convertion_data_and_alghoritms.symbol_table.CreateClassMethodScope(_ctn.scope, _cmn.scope, null, name);
|
||
cnfnn = new common_namespace_function_node(name, def_loc, _cmn, scope);
|
||
//_cmn.functions.AddElement(cnfnn);
|
||
syntax_tree_visitor.CompiledUnit.namespaces[0].functions.AddElement(cnfnn);
|
||
cnfnn.ConnectedToType = _ctn;
|
||
_last_created_function = new SymbolInfo(cnfnn);
|
||
if (add_symbol_info)
|
||
_ctn.scope.AddSymbol(name, _last_created_function);
|
||
cfn = cnfnn;
|
||
}
|
||
break;
|
||
}
|
||
case block_type.compiled_type_block:
|
||
{
|
||
//string cname = StringConstants.GetConnectedFunctionName(_compiled_tn.name, name);
|
||
common_namespace_function_node cnfnn;
|
||
SymbolTable.Scope scope = convertion_data_and_alghoritms.symbol_table.CreateClassMethodScope(_compiled_tn.scope, _cmn.scope, null, name);
|
||
cnfnn = new common_namespace_function_node(name, def_loc, _cmn, scope);
|
||
//_cmn.functions.AddElement(cnfnn);
|
||
syntax_tree_visitor.CompiledUnit.namespaces[0].functions.AddElement(cnfnn);
|
||
cnfnn.ConnectedToType = _compiled_tn;
|
||
_last_created_function = new SymbolInfo(cnfnn);
|
||
if (add_symbol_info)
|
||
_compiled_tn.scope.AddSymbol(name, _last_created_function);
|
||
List<SymbolInfo> sss = _compiled_tn.find_in_type("Hello");
|
||
cfn = cnfnn;
|
||
//if(_compiled_tn.compiled_type.IsPrimitive)
|
||
// syntax_tree_visitor.WarningsList.Add(new PascalABCCompiler.Errors.CompilerWarning
|
||
break;
|
||
}
|
||
case block_type.namespace_block:
|
||
{
|
||
common_namespace_function_node cnfnn;
|
||
SymbolTable.Scope scope = convertion_data_and_alghoritms.symbol_table.CreateScope(_cmn.scope, name);
|
||
cnfnn=new common_namespace_function_node(name,def_loc,_cmn,scope);
|
||
_cmn.functions.AddElement(cnfnn);
|
||
_last_created_function= new SymbolInfo(cnfnn);
|
||
if (add_symbol_info)
|
||
_cmn.scope.AddSymbol(name, _last_created_function);
|
||
cfn=cnfnn;
|
||
break;
|
||
}
|
||
}
|
||
_func_stack.push(cfn);
|
||
return cfn;
|
||
}
|
||
|
||
public common_type_node advanced_create_type(string name,location def_loc, bool type_is_interface, bool is_partial=false, SyntaxTree.class_attribute attr = SyntaxTree.class_attribute.None)
|
||
{
|
||
//check_name_free(name,def_loc);
|
||
common_type_node partial_class = null;
|
||
common_type_node rez = check_type_name_free_and_predop(name, def_loc, ref partial_class, is_partial);
|
||
if (rez != null)
|
||
{
|
||
if (is_partial && !(rez.ForwardDeclarationOnly && this.namespace_converted))
|
||
{
|
||
if (rez.ForwardDeclarationOnly)
|
||
AddError(rez.loc, "PARTIAL_CLASS_PREDEFINITION_NOT_ALLOWED");
|
||
if ((attr & SyntaxTree.class_attribute.Static) == SyntaxTree.class_attribute.Static && !rez.IsStatic)
|
||
AddError(def_loc, "PARTIAL_CLASS_ATTRIBUTES_MISMATCH");
|
||
if ((attr & SyntaxTree.class_attribute.Static) != SyntaxTree.class_attribute.Static && rez.IsStatic)
|
||
AddError(def_loc, "PARTIAL_CLASS_ATTRIBUTES_MISMATCH");
|
||
if ((attr & SyntaxTree.class_attribute.Abstract) == SyntaxTree.class_attribute.Abstract && !rez.IsAbstract)
|
||
AddError(def_loc, "PARTIAL_CLASS_ATTRIBUTES_MISMATCH");
|
||
if ((attr & SyntaxTree.class_attribute.Abstract) != SyntaxTree.class_attribute.Abstract && rez.IsAbstract && !rez.IsStatic)
|
||
AddError(def_loc, "PARTIAL_CLASS_ATTRIBUTES_MISMATCH");
|
||
if ((attr & SyntaxTree.class_attribute.Sealed) == SyntaxTree.class_attribute.Sealed && !rez.IsSealed)
|
||
AddError(def_loc, "PARTIAL_CLASS_ATTRIBUTES_MISMATCH");
|
||
if ((attr & SyntaxTree.class_attribute.Sealed) != SyntaxTree.class_attribute.Sealed && rez.IsSealed && !rez.IsStatic)
|
||
AddError(def_loc, "PARTIAL_CLASS_ATTRIBUTES_MISMATCH");
|
||
}
|
||
_ctn = rez;
|
||
if (def_loc != null)
|
||
_ctn.loc = def_loc;
|
||
_types_predefined.Remove(_ctn);
|
||
return rez;
|
||
}
|
||
if (converting_block() != block_type.namespace_block)
|
||
{
|
||
AddError(new ClassCanNotBeDefinedInTypeOrFunction(name, def_loc));
|
||
}
|
||
SymbolTable.ClassScope scope;
|
||
//(ssyy) Если создаётся интерфейс, то создаём ему специальный вид области видимости
|
||
if (type_is_interface)
|
||
{
|
||
scope = convertion_data_and_alghoritms.symbol_table.CreateInterfaceScope(_cmn.scope, null, "interface " + name);
|
||
}
|
||
else
|
||
{
|
||
scope = convertion_data_and_alghoritms.symbol_table.CreateClassScope(_cmn.scope, null, "class " + name);
|
||
}
|
||
common_type_node tctn=new common_type_node(name,SemanticTree.type_access_level.tal_public,_cmn,
|
||
scope,def_loc);
|
||
(scope as SymbolTable.ClassScope).class_type = tctn; // SSM 02.04.19 - каждый Scope пользовательского класса хранит свой type_node
|
||
|
||
tctn.is_class = true;
|
||
tctn.IsPartial = is_partial;
|
||
if (partial_class != null)
|
||
{
|
||
tctn.scope.PartialScope = partial_class.scope;
|
||
tctn.Merge(partial_class);
|
||
}
|
||
set_field_access_level(SemanticTree.field_access_level.fal_public);
|
||
_cmn.scope.AddSymbol(name,new SymbolInfo(tctn));
|
||
tctn.IsInterface = type_is_interface;
|
||
|
||
//_cmn.types.AddElement(tctn);
|
||
_ctn=tctn;
|
||
SystemLibrary.SystemLibrary.init_reference_type(tctn);
|
||
return tctn;
|
||
}
|
||
|
||
public common_type_node CreateTempCommonType(string nameTemplate, location def_loc)
|
||
{
|
||
int n=0;
|
||
while (_cmn.scope.Find(string.Format(nameTemplate, n)) != null)
|
||
n++;
|
||
string name = string.Format(nameTemplate, n);
|
||
SymbolTable.ClassScope scope = convertion_data_and_alghoritms.symbol_table.CreateClassScope(_cmn.scope, null, name);
|
||
common_type_node tctn = new common_type_node(name, SemanticTree.type_access_level.tal_internal, _cmn,
|
||
scope, def_loc);
|
||
_cmn.scope.AddSymbol(name, new SymbolInfo(tctn));
|
||
tctn.IsInterface = false;
|
||
tctn.is_class = true;
|
||
_cmn.types.AddElement(tctn);
|
||
_ctn = tctn;
|
||
SystemLibrary.SystemLibrary.init_reference_type(tctn);
|
||
return tctn;
|
||
}
|
||
|
||
public Stack<var_definition_node> loop_var_stack = new Stack<var_definition_node>();
|
||
|
||
public bool is_in_cycle()
|
||
{
|
||
return loop_var_stack.Count != 0;
|
||
}
|
||
|
||
public bool is_loop_variable(var_definition_node vdn)
|
||
{
|
||
return loop_var_stack.Contains(vdn);
|
||
}
|
||
|
||
|
||
public common_type_node create_type(string name, location def_loc)
|
||
{
|
||
return advanced_create_type(name, def_loc, false);
|
||
}
|
||
|
||
public common_type_node create_typed_file_type(type_node elem_type, location def_loc)
|
||
{
|
||
if (TypedFiles.ContainsKey(elem_type))
|
||
return TypedFiles[elem_type];
|
||
string name = StringConstants.GetTypedFileTypeName(elem_type.name);
|
||
type_node base_type = SystemLibrary.SystemLibInitializer.TypedFileType.sym_info as type_node;
|
||
//check_name_free(name, def_loc);
|
||
SymbolTable.ClassScope scope = convertion_data_and_alghoritms.symbol_table.CreateClassScope(_cmn.scope, null, name);
|
||
common_type_node tctn = new common_type_node(name, SemanticTree.type_access_level.tal_public, _cmn,
|
||
scope, def_loc);
|
||
set_field_access_level(SemanticTree.field_access_level.fal_public);
|
||
_cmn.scope.AddSymbol(name, new SymbolInfo(tctn));
|
||
tctn.type_special_kind = SemanticTree.type_special_kind.typed_file;
|
||
tctn.element_type = elem_type;
|
||
tctn.internal_is_value = base_type.is_value;
|
||
tctn.is_class = base_type.is_class;
|
||
tctn.SetBaseType(base_type);
|
||
//_ctn = tctn;
|
||
SystemLibrary.SystemLibrary.init_reference_type(tctn);
|
||
converted_namespace.types.AddElement(tctn);
|
||
TypedFiles.Add(elem_type, tctn);
|
||
return tctn;
|
||
}
|
||
|
||
public common_type_node create_set_type(type_node elem_type, location def_loc)
|
||
{
|
||
if (TypedSets.ContainsKey(elem_type))
|
||
return TypedSets[elem_type];
|
||
string name = StringConstants.GetSetTypeName(elem_type.name);
|
||
type_node base_type = SystemLibrary.SystemLibInitializer.TypedSetType.sym_info as type_node;
|
||
//check_name_free(name, def_loc);
|
||
SymbolTable.ClassScope scope = convertion_data_and_alghoritms.symbol_table.CreateClassScope(_cmn.scope, null, "set_type " + name);
|
||
common_type_node tctn = new common_type_node(name, SemanticTree.type_access_level.tal_public, _cmn,
|
||
scope, def_loc);
|
||
set_field_access_level(SemanticTree.field_access_level.fal_public);
|
||
_cmn.scope.AddSymbol(name, new SymbolInfo(tctn));
|
||
tctn.type_special_kind = SemanticTree.type_special_kind.set_type;
|
||
tctn.element_type = elem_type;
|
||
tctn.internal_is_value = base_type.is_value;
|
||
tctn.is_class = base_type.is_class;
|
||
tctn.SetBaseType(base_type);
|
||
tctn.add_name(StringConstants.assign_name,new SymbolInfo(SystemLibrary.SystemLibrary.make_assign_operator(tctn,PascalABCCompiler.SemanticTree.basic_function_type.objassign)));
|
||
tctn.ImplementingInterfaces.Add(compiled_type_node.get_type_node(NetHelper.NetHelper.FindType(StringConstants.IEnumerableInterfaceName)));
|
||
tctn.scope.AddSymbol(StringConstants.plus_name, SystemLibrary.SystemLibInitializer.SetUnionProcedure.SymbolInfo.FirstOrDefault());
|
||
tctn.scope.AddSymbol(StringConstants.mul_name, SystemLibrary.SystemLibInitializer.SetIntersectProcedure.SymbolInfo.FirstOrDefault());
|
||
tctn.scope.AddSymbol(StringConstants.in_name, SystemLibrary.SystemLibInitializer.InSetProcedure.SymbolInfo.FirstOrDefault());
|
||
tctn.scope.AddSymbol(StringConstants.minus_name, SystemLibrary.SystemLibInitializer.SetSubtractProcedure.SymbolInfo.FirstOrDefault());
|
||
tctn.scope.AddSymbol(StringConstants.eq_name, SystemLibrary.SystemLibInitializer.CompareSetEquals.SymbolInfo.FirstOrDefault());
|
||
tctn.scope.AddSymbol(StringConstants.noteq_name, SystemLibrary.SystemLibInitializer.CompareSetInEquals.SymbolInfo.FirstOrDefault());
|
||
tctn.scope.AddSymbol(StringConstants.sm_name, SystemLibrary.SystemLibInitializer.CompareSetLess.SymbolInfo.FirstOrDefault());
|
||
tctn.scope.AddSymbol(StringConstants.smeq_name, SystemLibrary.SystemLibInitializer.CompareSetLessEqual.SymbolInfo.FirstOrDefault());
|
||
tctn.scope.AddSymbol(StringConstants.gr_name, SystemLibrary.SystemLibInitializer.CompareSetGreater.SymbolInfo.FirstOrDefault());
|
||
tctn.scope.AddSymbol(StringConstants.greq_name, SystemLibrary.SystemLibInitializer.CompareSetGreaterEqual.SymbolInfo.FirstOrDefault());
|
||
tctn.scope.AddSymbol(StringConstants.plusassign_name,new SymbolInfo(make_set_plus_assign(tctn)));
|
||
tctn.scope.AddSymbol(StringConstants.minusassign_name,new SymbolInfo(make_set_minus_assign(tctn)));
|
||
tctn.scope.AddSymbol(StringConstants.multassign_name,new SymbolInfo(make_set_mult_assign(tctn)));
|
||
converted_namespace.types.AddElement(tctn);
|
||
TypedSets.Add(elem_type, tctn);
|
||
return tctn;
|
||
}
|
||
|
||
private static basic_function_node make_set_plus_assign(common_type_node ctn)
|
||
{
|
||
//basic_function_node bfn = new basic_function_node(SemanticTree.basic_function_type.objassign,ctn,false);
|
||
basic_function_node bfn = SystemLibrary.SystemLibrary.make_binary_operator(StringConstants.plusassign_name,ctn,SemanticTree.basic_function_type.objassign);
|
||
bfn.compile_time_executor = SystemLibrary.static_executors.set_plusassign_executor;
|
||
return bfn;
|
||
}
|
||
|
||
private static basic_function_node make_set_minus_assign(common_type_node ctn)
|
||
{
|
||
//basic_function_node bfn = new basic_function_node(SemanticTree.basic_function_type.objassign,ctn,false);
|
||
basic_function_node bfn = SystemLibrary.SystemLibrary.make_binary_operator(StringConstants.minusassign_name,ctn,SemanticTree.basic_function_type.objassign);
|
||
bfn.compile_time_executor = SystemLibrary.static_executors.set_subassign_executor;
|
||
return bfn;
|
||
}
|
||
|
||
private static basic_function_node make_set_mult_assign(common_type_node ctn)
|
||
{
|
||
//basic_function_node bfn = new basic_function_node(SemanticTree.basic_function_type.objassign,ctn,false);
|
||
basic_function_node bfn = SystemLibrary.SystemLibrary.make_binary_operator(StringConstants.multassign_name,ctn,SemanticTree.basic_function_type.objassign);
|
||
bfn.compile_time_executor = SystemLibrary.static_executors.set_multassign_executor;
|
||
return bfn;
|
||
}
|
||
|
||
private static basic_function_node make_short_string_plus_assign(short_string_type_node ctn)
|
||
{
|
||
basic_function_node bfn = SystemLibrary.SystemLibrary.make_binary_operator(StringConstants.plusassign_name,ctn,SemanticTree.basic_function_type.objassign);
|
||
bfn.compile_time_executor = SystemLibrary.static_executors.short_string_addassign_executor;
|
||
return bfn;
|
||
}
|
||
|
||
public template_class create_template_class(string name, byte[] tree)
|
||
{
|
||
Dictionary<string, template_class> tc_dict = null;
|
||
template_class tc = null;
|
||
if (compiled_tc_cache.TryGetValue(converted_namespace, out tc_dict) && tc_dict.TryGetValue(name, out tc))
|
||
return tc;
|
||
|
||
SyntaxTree.SyntaxTreeStreamReader str = new SyntaxTree.SyntaxTreeStreamReader();
|
||
str.br = new System.IO.BinaryReader(new System.IO.MemoryStream(tree));
|
||
SyntaxTree.type_declaration t_d = str._read_node() as SyntaxTree.type_declaration;
|
||
tc = new template_class(t_d, name, converted_namespace, null, new using_namespace_list());
|
||
tc.is_synonym = true;
|
||
if (tc_dict == null)
|
||
{
|
||
tc_dict = new Dictionary<string, template_class>();
|
||
compiled_tc_cache[converted_namespace] = tc_dict;
|
||
}
|
||
tc_dict[name] = tc;
|
||
return tc;
|
||
}
|
||
|
||
public short_string_type_node create_short_string_type(int length, location def_loc)
|
||
{
|
||
if (ShortStringTypes.ContainsKey(length))
|
||
return ShortStringTypes[length];
|
||
SymbolTable.ClassScope scope = convertion_data_and_alghoritms.symbol_table.CreateClassScope(null, SystemLibrary.SystemLibrary.string_type.Scope, "short_string_type");
|
||
short_string_type_node tctn = new short_string_type_node(//SemanticTree.type_access_level.tal_public, _cmn,
|
||
scope, def_loc, length);
|
||
tctn.add_name(StringConstants.assign_name,new SymbolInfo(SystemLibrary.SystemLibrary.make_assign_operator(tctn,PascalABCCompiler.SemanticTree.basic_function_type.objassign)));
|
||
tctn.add_name(StringConstants.plus_name,new SymbolInfo(SystemLibrary.SystemLibrary.string_add));
|
||
tctn.scope.AddSymbol(StringConstants.plusassign_name,new SymbolInfo(make_short_string_plus_assign(tctn)));
|
||
type_intersection_node inter = new type_intersection_node(type_compare.greater_type);
|
||
inter.another_to_this = new type_conversion(SystemLibrary.SystemLibrary.char_to_string);
|
||
tctn.add_intersection_node(SystemLibrary.SystemLibrary.char_type, inter,false);
|
||
ShortStringTypes.Add(length, tctn);
|
||
return tctn;
|
||
}
|
||
|
||
/****************************modified***********************/
|
||
private int rec_num=0;
|
||
|
||
public common_type_node create_record_type(location def_loc, string name)
|
||
{
|
||
if (name == null)
|
||
name = "$record$" + rec_num++;
|
||
SymbolTable.ClassScope scope = convertion_data_and_alghoritms.symbol_table.CreateClassScope(_cmn.scope, null, "record " + name);
|
||
common_type_node tctn = new common_type_node(name, SemanticTree.type_access_level.tal_public, _cmn,
|
||
scope, def_loc);
|
||
if (top_function != null)
|
||
tctn.defined_in_scope = top_function.scope;
|
||
set_field_access_level(SemanticTree.field_access_level.fal_public);
|
||
tctn.SetBaseType(SemanticRulesConstants.StructBaseType);
|
||
if (_ctn != null) type_stack.Push(_ctn);
|
||
add_type(name, tctn, def_loc);
|
||
_ctn = tctn;
|
||
tctn.type_special_kind = SemanticTree.type_special_kind.record;
|
||
SystemLibrary.SystemLibrary.init_reference_type(tctn);
|
||
tctn.internal_is_value = true;
|
||
return tctn;
|
||
|
||
}
|
||
|
||
public void create_generic_indicator(common_type_node generic)
|
||
{
|
||
generic_indicator gi = new generic_indicator(generic);
|
||
int pos = generic.name.LastIndexOf(StringConstants.generic_params_infix);
|
||
string name = generic.name.Substring(0, pos);
|
||
_cmn.scope.AddSymbol(name, new SymbolInfo(gi, access_level.al_public, symbol_kind.sk_none));
|
||
}
|
||
|
||
public void save_var_definitions()
|
||
{
|
||
var_defs_stack.Push(var_defs);
|
||
var_defs = new System.Collections.Generic.List<var_definition_node>();
|
||
}
|
||
|
||
public void restore_var_definitions()
|
||
{
|
||
var_defs = var_defs_stack.Pop();
|
||
}
|
||
|
||
public string BuildName(string name)
|
||
{
|
||
if (converting_block() == block_type.function_block)
|
||
{
|
||
return name + "$" + rec_num++;
|
||
}
|
||
else
|
||
{
|
||
return name;
|
||
}
|
||
}
|
||
/*************************************************************/
|
||
|
||
internal statements_list CurrentStatementList
|
||
{
|
||
get
|
||
{
|
||
if (!syntax_tree_visitor.convertion_data_and_alghoritms.statement_list_stack.Empty)
|
||
return syntax_tree_visitor.convertion_data_and_alghoritms.statement_list_stack.top();
|
||
return null;
|
||
}
|
||
}
|
||
|
||
|
||
public var_definition_node add_var_definition(string name, location loc)
|
||
{
|
||
return add_var_definition(name, loc, SemanticTree.polymorphic_state.ps_common);
|
||
}
|
||
public var_definition_node add_var_definition(string name, location loc, SemanticTree.polymorphic_state ps)
|
||
{
|
||
return add_var_definition(name, loc, null, ps);
|
||
}
|
||
|
||
public var_definition_node add_var_definition(string name, location loc, type_node tn, expression_node inital_value)
|
||
{
|
||
var_definition_node vdn = add_var_definition(name, loc, tn, SemanticTree.polymorphic_state.ps_common);
|
||
vdn.inital_value = GetInitalValueForVariable(vdn, inital_value);
|
||
return vdn;
|
||
}
|
||
|
||
public var_definition_node add_var_definition_in_entry_scope(string name, location loc)
|
||
{
|
||
namespace_variable nsv=new namespace_variable(name,null,_cmn,loc);
|
||
//_cmn.scope.AddSymbol(name,new SymbolInfo(nsv));
|
||
CurrentScope.AddSymbol(name, new SymbolInfo(nsv));
|
||
_cmn.variables.AddElement(nsv);
|
||
var_defs.Add(nsv);
|
||
return nsv;
|
||
}
|
||
|
||
public common_namespace_event add_namespace_event(string name, location loc, type_node tn)
|
||
{
|
||
namespace_variable nv = new namespace_variable(name + "$", tn, converted_namespace, loc);
|
||
common_namespace_event cne = new common_namespace_event(name, tn, converted_namespace, null, null, null, loc);
|
||
common_namespace_function_node add_func = new common_namespace_function_node(StringConstants.GetAddHandler(name),
|
||
null, this.converted_namespace, null);
|
||
common_parameter cp = new common_parameter("value", tn, SemanticTree.parameter_type.value, add_func, concrete_parameter_type.cpt_none, null, null);
|
||
add_func.parameters.AddElement(cp);
|
||
expression_node fld_ref = null;
|
||
fld_ref = new namespace_variable_reference(nv, null);
|
||
expression_node en = this.syntax_tree_visitor.convertion_data_and_alghoritms.type_constructor.delegate_add_assign_compile_time_executor
|
||
(null, new expression_node[2] { fld_ref, new common_parameter_reference(cp, 0, null) });
|
||
//en = this.syntax_tree_visitor.convertion_data_and_alghoritms.create_simple_function_call(tn.find_in_type(StringConstants.assign_name).sym_info as function_node,null,
|
||
// fld_ref,en);
|
||
add_func.function_code = new statements_list(null);
|
||
(add_func.function_code as statements_list).statements.AddElement(en);
|
||
//remove
|
||
common_namespace_function_node remove_func = new common_namespace_function_node(StringConstants.GetRemoveHandler(name), null, this.converted_namespace, null);
|
||
|
||
cp = new common_parameter("value", tn, SemanticTree.parameter_type.value, add_func, concrete_parameter_type.cpt_none, null, null);
|
||
remove_func.parameters.AddElement(cp);
|
||
en = this.syntax_tree_visitor.convertion_data_and_alghoritms.type_constructor.delegate_sub_assign_compile_time_executor
|
||
(null, new expression_node[2] { fld_ref, new common_parameter_reference(cp, 0, null) });
|
||
//en = this.syntax_tree_visitor.convertion_data_and_alghoritms.create_simple_function_call(tn.find_in_type(StringConstants.assign_name).sym_info as function_node,null,
|
||
// fld_ref,en);
|
||
remove_func.function_code = new statements_list(null);
|
||
(remove_func.function_code as statements_list).statements.AddElement(en);
|
||
this.converted_namespace.functions.AddElement(add_func);
|
||
this.converted_namespace.functions.AddElement(remove_func);
|
||
cne.set_add_function(add_func);
|
||
cne.set_remove_function(remove_func);
|
||
cne.field = nv;
|
||
this.converted_namespace.events.AddElement(cne);
|
||
this.converted_namespace.variables.AddElement(nv);
|
||
CurrentScope.AddSymbol(name, new SymbolInfo(cne));
|
||
return cne;
|
||
}
|
||
|
||
public common_event add_event_definition(string name, location loc, type_node tn, SemanticTree.polymorphic_state ps, bool is_abstract)
|
||
{
|
||
class_field cf = new class_field(name + "$", tn, converted_type, ps, _fal, loc);
|
||
common_event ce = new common_event(name, tn, converted_type, null, null, null, _fal, ps, loc);
|
||
//add
|
||
common_method_node add_meth = new common_method_node(StringConstants.GetAddHandler(name), null, this.converted_type,
|
||
ps, SemanticTree.field_access_level.fal_public, null);
|
||
common_parameter cp = new common_parameter("value", tn, SemanticTree.parameter_type.value, add_meth, concrete_parameter_type.cpt_none, null, null);
|
||
add_meth.parameters.AddElement(cp);
|
||
expression_node fld_ref = null;
|
||
if (!cf.IsStatic) fld_ref = new class_field_reference(cf, new this_node(converted_type, null), null);
|
||
else fld_ref = new static_class_field_reference(cf, null);
|
||
expression_node en = this.syntax_tree_visitor.convertion_data_and_alghoritms.type_constructor.delegate_add_assign_compile_time_executor
|
||
(null, new expression_node[2] { fld_ref, new common_parameter_reference(cp, 0, null) });
|
||
|
||
if (!is_abstract)
|
||
{
|
||
add_meth.function_code = new statements_list(null);
|
||
(add_meth.function_code as statements_list).statements.AddElement(en);
|
||
}
|
||
converted_type.scope.AddSymbol(add_meth.name, new SymbolInfo(add_meth));
|
||
//remove
|
||
common_method_node remove_meth = new common_method_node(StringConstants.GetRemoveHandler(name), null, this.converted_type,
|
||
ps, SemanticTree.field_access_level.fal_public, null);
|
||
|
||
cp = new common_parameter("value", tn, SemanticTree.parameter_type.value, add_meth, concrete_parameter_type.cpt_none, null, null);
|
||
remove_meth.parameters.AddElement(cp);
|
||
en = this.syntax_tree_visitor.convertion_data_and_alghoritms.type_constructor.delegate_sub_assign_compile_time_executor
|
||
(null, new expression_node[2] { fld_ref, new common_parameter_reference(cp, 0, null) });
|
||
if (!is_abstract)
|
||
{
|
||
remove_meth.function_code = new statements_list(null);
|
||
(remove_meth.function_code as statements_list).statements.AddElement(en);
|
||
}
|
||
converted_type.scope.AddSymbol(remove_meth.name, new SymbolInfo(remove_meth));
|
||
this.converted_type.methods.AddElement(add_meth);
|
||
this.converted_type.methods.AddElement(remove_meth);
|
||
ce.set_add_method(add_meth);
|
||
ce.set_remove_method(remove_meth);
|
||
ce.field = cf;
|
||
this.converted_type.events.AddElement(ce);
|
||
if (!is_abstract)
|
||
this.converted_type.fields.AddElement(cf);
|
||
converted_type.scope.AddSymbol(name, new SymbolInfo(ce));
|
||
return ce;
|
||
}
|
||
|
||
public bool check_name_redefinition = true;
|
||
|
||
public var_definition_node add_field(string name, location loc, type_node tn, SemanticTree.polymorphic_state ps)
|
||
{
|
||
class_field cf = new class_field(name, tn, _ctn, ps, _fal, loc);
|
||
//_ctn.Scope.AddSymbol(name,new SymbolInfo(cf));
|
||
CurrentScope.AddSymbol(name, new SymbolInfo(cf));
|
||
_ctn.fields.AddElement(cf);
|
||
return cf;
|
||
}
|
||
|
||
public var_definition_node add_var_definition(string name, location loc, type_node tn, SemanticTree.polymorphic_state ps, bool not_add_to_varlist=false)
|
||
{
|
||
check_name_free(name,loc);
|
||
var_definition_node vdn=null;
|
||
if (CurrentScope is SymbolTable.BlockScope)
|
||
{
|
||
if (SemanticRulesConstants.DisabledDefinitionBlockVariablesWithSameNameThatInAboveScope)
|
||
{
|
||
SymbolTable.Scope cs = CurrentScope;
|
||
while (cs.TopScope != null /*(cs.TopScope is SymbolTable.BlockScope || cs.TopScope is SymbolTable.UnitPartScope)*/)
|
||
{
|
||
if (cs.TopScope is SymbolTable.BlockScope)//projdemsja po blokam koda
|
||
{
|
||
if (cs.TopScope.FindOnlyInScope(name) != null)
|
||
syntax_tree_visitor.AddError(loc, "BLOCK_VARIABLES_CANNOT_HAVE_NAMES_UPPER_SCOPE");
|
||
cs = cs.TopScope;
|
||
}
|
||
else // a zdes proverjaem v verhnem bloke i vse, to chto eshe vyshe, tam ne proverjaem, tak dejstvuet princip blochnosti
|
||
{
|
||
if (cs.TopScope.FindOnlyInScope(name) != null)
|
||
syntax_tree_visitor.AddError(loc, "BLOCK_VARIABLES_CANNOT_HAVE_NAMES_UPPER_SCOPE");
|
||
break;
|
||
}
|
||
|
||
}
|
||
}
|
||
local_block_variable lv = new local_block_variable(name, tn, CurrentStatementList, loc);
|
||
CurrentScope.AddSymbol(name, new SymbolInfo(lv));
|
||
if (!not_add_to_varlist)
|
||
lv.block.local_variables.Add(lv);
|
||
if (tn == null) //Тип еще неизвестен, будем закрывать.
|
||
var_defs.Add(lv);
|
||
if (syntax_tree_visitor.for_intellisense)
|
||
syntax_tree_visitor.CompiledVariables.Add(lv);
|
||
return lv;
|
||
}
|
||
switch (converting_block())
|
||
{
|
||
case block_type.function_block:
|
||
{
|
||
common_function_node top_func = _func_stack.top();
|
||
local_variable lv=new local_variable(name,tn,top_func,loc);
|
||
vdn=lv;
|
||
top_func.var_definition_nodes_list.AddElement(lv);
|
||
CurrentScope.AddSymbol(name, new SymbolInfo(lv));
|
||
//top_func.scope.AddSymbol(name,new SymbolInfo(lv));
|
||
break;
|
||
}
|
||
case block_type.type_block:
|
||
{
|
||
//TODO:сделать static и virtual.
|
||
class_field cf = new class_field(name,tn, _ctn, ps,_fal,loc);
|
||
vdn=cf;
|
||
//_ctn.Scope.AddSymbol(name,new SymbolInfo(cf));
|
||
CurrentScope.AddSymbol(name, new SymbolInfo(cf));
|
||
_ctn.fields.AddElement(cf);
|
||
break;
|
||
}
|
||
case block_type.namespace_block:
|
||
{
|
||
namespace_variable nsv=new namespace_variable(name,tn,_cmn,loc);
|
||
vdn=nsv;
|
||
//_cmn.scope.AddSymbol(name,new SymbolInfo(nsv));
|
||
CurrentScope.AddSymbol(name, new SymbolInfo(nsv));
|
||
_cmn.variables.AddElement(nsv);
|
||
break;
|
||
}
|
||
}
|
||
if (tn == null) //Тип еще неизвестен, будем закрывать.
|
||
var_defs.Add(vdn);
|
||
if (syntax_tree_visitor.for_intellisense)
|
||
syntax_tree_visitor.CompiledVariables.Add(vdn);
|
||
return vdn;
|
||
}
|
||
|
||
//ssyy
|
||
public label_node add_label_declaration(string name, location loc)
|
||
{
|
||
check_name_free(name, loc);
|
||
label_node lab = new label_node(name, loc);
|
||
switch (converting_block())
|
||
{
|
||
case block_type.function_block:
|
||
{
|
||
common_function_node top_func = _func_stack.top();
|
||
top_func.label_nodes_list.Add(lab);
|
||
top_func.scope.AddSymbol(name, new SymbolInfo(lab));
|
||
break;
|
||
}
|
||
case block_type.namespace_block:
|
||
{
|
||
_cmn.scope.AddSymbol(name, new SymbolInfo(lab));
|
||
_cmn.labels.Add(lab);
|
||
break;
|
||
}
|
||
default:
|
||
{
|
||
AddError(loc, "LABEL_CAN_NOT_BE_DECLARED_HERE");
|
||
break;
|
||
}
|
||
}
|
||
return lab;
|
||
}
|
||
//\ssyy
|
||
|
||
private int num_of_for_cycles
|
||
{
|
||
get
|
||
{
|
||
switch (converting_block())
|
||
{
|
||
case block_type.function_block:
|
||
{
|
||
return top_function.num_of_for_cycles;
|
||
}
|
||
case block_type.namespace_block:
|
||
{
|
||
return _num_of_for_cycles;
|
||
}
|
||
case block_type.type_block:
|
||
{
|
||
throw new CompilerInternalError("For cycle in class body");
|
||
//return 0;
|
||
}
|
||
}
|
||
throw new CompilerInternalError("Invalid block type");
|
||
}
|
||
set
|
||
{
|
||
switch (converting_block())
|
||
{
|
||
case block_type.function_block:
|
||
{
|
||
top_function.num_of_for_cycles=value;
|
||
break;
|
||
}
|
||
case block_type.namespace_block:
|
||
{
|
||
//TODO: Переделать. Число циклов не должно хранится в функции.
|
||
_num_of_for_cycles=value;
|
||
break;
|
||
}
|
||
case block_type.type_block:
|
||
{
|
||
throw new CompilerInternalError("For cycle in class body");
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
private int get_and_postinc_num_of_for_cycles()
|
||
{
|
||
int temp = _num_of_for_cycles;
|
||
_num_of_for_cycles++;
|
||
return temp;
|
||
}
|
||
|
||
public string get_delegate_type_name()
|
||
{
|
||
return (StringConstants.delegate_type_name_template + _num_for_delegates++);
|
||
}
|
||
|
||
public var_definition_node create_for_temp_variable(type_node type,location loc)
|
||
{
|
||
num_of_for_cycles=num_of_for_cycles+1;
|
||
string name=StringConstants.temp_for_variable_name+num_of_for_cycles.ToString();
|
||
//return create_temp_variable(name,type,loc);
|
||
return add_var_definition(name, loc, type, SemanticTree.polymorphic_state.ps_common);
|
||
}
|
||
|
||
public var_definition_node create_temp_variable(string name,type_node type,location loc)
|
||
{
|
||
var_definition_node vdn=null;
|
||
switch (converting_block())
|
||
{
|
||
case block_type.function_block:
|
||
{
|
||
common_function_node top_func = _func_stack.top();
|
||
local_variable lv=new local_variable(name,type,top_func,loc);
|
||
vdn=lv;
|
||
top_func.var_definition_nodes_list.AddElement(lv);
|
||
break;
|
||
}
|
||
case block_type.type_block:
|
||
{
|
||
//TODO:сделать static и virtual.
|
||
class_field cf=new class_field(name,type,_ctn,SemanticTree.polymorphic_state.ps_common,_fal,loc);
|
||
vdn=cf;
|
||
_ctn.fields.AddElement(cf);
|
||
break;
|
||
}
|
||
case block_type.namespace_block:
|
||
{
|
||
namespace_variable nsv=new namespace_variable(name,type,_cmn,loc);
|
||
vdn=nsv;
|
||
_cmn.variables.AddElement(nsv);
|
||
break;
|
||
}
|
||
}
|
||
return vdn;
|
||
}
|
||
|
||
public common_parameter add_parameter(string name,SemanticTree.parameter_type pt,
|
||
concrete_parameter_type cpt,location loc)
|
||
{
|
||
check_name_free(name,loc);
|
||
#if (DEBUG)
|
||
if (converting_block()!=block_type.function_block)
|
||
{
|
||
throw new CompilerInternalError("Parameters can be defined with functions only");
|
||
}
|
||
#endif
|
||
common_function_node top_func = _func_stack.top();
|
||
common_parameter cp=new common_parameter(name,pt,top_func,cpt,loc);
|
||
top_func.parameters.AddElement(cp);
|
||
top_func.scope.AddSymbol(name,new SymbolInfo(cp));
|
||
var_defs.Add(cp);
|
||
return cp;
|
||
}
|
||
|
||
public constant_definition_node add_const_definition(string name,location loc)
|
||
{
|
||
constant_definition_node cdn=null;
|
||
//cdn.loc=loc;
|
||
check_name_free(name, loc);
|
||
switch (converting_block())
|
||
{
|
||
case block_type.function_block:
|
||
{
|
||
common_function_node top_func = _func_stack.top();
|
||
function_constant_definition fcd = new function_constant_definition(name, loc, top_func);
|
||
top_func.scope.AddSymbol(name,new SymbolInfo(fcd));
|
||
top_func.constants.AddElement(fcd);
|
||
cdn = fcd;
|
||
break;
|
||
}
|
||
case block_type.type_block:
|
||
{
|
||
class_constant_definition ccd = new class_constant_definition(name, loc, _ctn, _fal);
|
||
_ctn.Scope.AddSymbol(name,new SymbolInfo(ccd));
|
||
_ctn.const_defs.AddElement(ccd);
|
||
cdn = ccd;
|
||
break;
|
||
}
|
||
case block_type.namespace_block:
|
||
{
|
||
namespace_constant_definition ncd = new namespace_constant_definition(name, loc, _cmn);
|
||
_cmn.scope.AddSymbol(name,new SymbolInfo(ncd));
|
||
_cmn.constants.AddElement(ncd);
|
||
cdn = ncd;
|
||
break;
|
||
}
|
||
}
|
||
return cdn;
|
||
}
|
||
|
||
public static void add_convertions_to_enum_type(common_type_node tctn)
|
||
{
|
||
SystemLibrary.SystemLibrary.make_binary_operator(StringConstants.gr_name,tctn,SemanticTree.basic_function_type.enumgr,SystemLibrary.SystemLibrary.bool_type);
|
||
SystemLibrary.SystemLibrary.make_binary_operator(StringConstants.greq_name,tctn,SemanticTree.basic_function_type.enumgreq,SystemLibrary.SystemLibrary.bool_type);
|
||
SystemLibrary.SystemLibrary.make_binary_operator(StringConstants.sm_name,tctn,SemanticTree.basic_function_type.enumsm,SystemLibrary.SystemLibrary.bool_type);
|
||
SystemLibrary.SystemLibrary.make_binary_operator(StringConstants.smeq_name,tctn,SemanticTree.basic_function_type.enumsmeq,SystemLibrary.SystemLibrary.bool_type);
|
||
SystemLibrary.SystemLibrary.make_binary_operator(StringConstants.or_name, tctn, SemanticTree.basic_function_type.enumsor, tctn);
|
||
SystemLibrary.SystemLibrary.make_binary_operator(StringConstants.and_name, tctn, SemanticTree.basic_function_type.enumsand, tctn);
|
||
SystemLibrary.SystemLibrary.make_binary_operator(StringConstants.xor_name, tctn, SemanticTree.basic_function_type.enumsxor, tctn);
|
||
|
||
SystemLibrary.SystemLibrary.make_generated_type_conversion(tctn,SystemLibrary.SystemLibrary.byte_type,type_compare.greater_type,PascalABCCompiler.SemanticTree.basic_function_type.itob,false);
|
||
SystemLibrary.SystemLibrary.make_generated_type_conversion(tctn,SystemLibrary.SystemLibrary.sbyte_type,type_compare.greater_type,PascalABCCompiler.SemanticTree.basic_function_type.itosb,false);
|
||
SystemLibrary.SystemLibrary.make_generated_type_conversion(tctn,SystemLibrary.SystemLibrary.short_type,type_compare.greater_type,PascalABCCompiler.SemanticTree.basic_function_type.itos,false);
|
||
SystemLibrary.SystemLibrary.make_generated_type_conversion(tctn,SystemLibrary.SystemLibrary.ushort_type,type_compare.greater_type,PascalABCCompiler.SemanticTree.basic_function_type.itous,false);
|
||
SystemLibrary.SystemLibrary.make_generated_type_conversion(tctn,SystemLibrary.SystemLibrary.integer_type,type_compare.less_type,PascalABCCompiler.SemanticTree.basic_function_type.none,false);
|
||
SystemLibrary.SystemLibrary.make_generated_type_conversion(tctn,SystemLibrary.SystemLibrary.uint_type,type_compare.less_type,PascalABCCompiler.SemanticTree.basic_function_type.itoui,false);
|
||
SystemLibrary.SystemLibrary.make_generated_type_conversion(tctn,SystemLibrary.SystemLibrary.int64_type,type_compare.less_type,PascalABCCompiler.SemanticTree.basic_function_type.itol,false);
|
||
SystemLibrary.SystemLibrary.make_generated_type_conversion(tctn,SystemLibrary.SystemLibrary.uint64_type,type_compare.less_type,PascalABCCompiler.SemanticTree.basic_function_type.itoul,false);
|
||
|
||
SystemLibrary.SystemLibrary.make_generated_type_conversion(SystemLibrary.SystemLibrary.byte_type,tctn,type_compare.less_type,PascalABCCompiler.SemanticTree.basic_function_type.btoi,false);
|
||
SystemLibrary.SystemLibrary.make_generated_type_conversion(SystemLibrary.SystemLibrary.sbyte_type,tctn,type_compare.less_type,PascalABCCompiler.SemanticTree.basic_function_type.sbtoi,false);
|
||
SystemLibrary.SystemLibrary.make_generated_type_conversion(SystemLibrary.SystemLibrary.short_type,tctn,type_compare.less_type,PascalABCCompiler.SemanticTree.basic_function_type.stoi,false);
|
||
SystemLibrary.SystemLibrary.make_generated_type_conversion(SystemLibrary.SystemLibrary.ushort_type,tctn,type_compare.less_type,PascalABCCompiler.SemanticTree.basic_function_type.ustoi,false);
|
||
SystemLibrary.SystemLibrary.make_generated_type_conversion(SystemLibrary.SystemLibrary.integer_type,tctn,type_compare.greater_type,PascalABCCompiler.SemanticTree.basic_function_type.none,false);
|
||
SystemLibrary.SystemLibrary.make_generated_type_conversion(SystemLibrary.SystemLibrary.uint_type,tctn,type_compare.greater_type,PascalABCCompiler.SemanticTree.basic_function_type.uitoi,false);
|
||
SystemLibrary.SystemLibrary.make_generated_type_conversion(SystemLibrary.SystemLibrary.int64_type,tctn,type_compare.greater_type,PascalABCCompiler.SemanticTree.basic_function_type.ltoi,false);
|
||
SystemLibrary.SystemLibrary.make_generated_type_conversion(SystemLibrary.SystemLibrary.uint64_type,tctn,type_compare.greater_type,PascalABCCompiler.SemanticTree.basic_function_type.ultoi,false);
|
||
}
|
||
|
||
public common_type_node create_enum_type(string name, location def_loc)
|
||
{
|
||
if (name == null)
|
||
name = "$enum$" + rec_num++;
|
||
SymbolTable.ClassScope scope = convertion_data_and_alghoritms.symbol_table.CreateClassScope(_cmn.scope, null, "enum_type " + name);
|
||
common_type_node tctn = new common_type_node(name, SemanticTree.type_access_level.tal_public, _cmn,
|
||
scope, def_loc);
|
||
if (top_function != null)
|
||
tctn.defined_in_scope = top_function.scope;
|
||
set_field_access_level(SemanticTree.field_access_level.fal_public);
|
||
//_cmn.scope.AddSymbol(name, new SymbolInfo(tctn));
|
||
tctn.SetBaseType(compiled_type_node.get_type_node(NetHelper.NetHelper.EnumType));
|
||
tctn.internal_is_value = true;
|
||
|
||
add_convertions_to_enum_type(tctn);
|
||
if (_ctn != null) type_stack.Push(_ctn);
|
||
add_type(name, tctn, def_loc);
|
||
_ctn = tctn;
|
||
SystemLibrary.SystemLibrary.init_reference_type(tctn);
|
||
return tctn;
|
||
}
|
||
|
||
public void close_var_definition_list(type_node tp, expression_node inital_value)
|
||
{
|
||
if (var_defs.Count==0)
|
||
return;
|
||
int count = var_defs.Count;
|
||
for (int i=0; i<count; i++)
|
||
{
|
||
var_defs[i].type = tp;
|
||
bool flag = false;
|
||
if (var_defs[i] is common_parameter && ((var_defs[i] as common_parameter).parameter_type == SemanticTree.parameter_type.var || (var_defs[i] as common_parameter).concrete_parameter_type == concrete_parameter_type.cpt_const))
|
||
flag = true;
|
||
if (!flag)
|
||
var_defs[i].inital_value = GetInitalValueForVariable(var_defs[i],inital_value);
|
||
}
|
||
var_defs.Clear();
|
||
}
|
||
|
||
private bool IsConstructorCall(expression_node expr)
|
||
{
|
||
return (expr is common_constructor_call) || (expr is compiled_constructor_call);
|
||
}
|
||
|
||
internal expression_node GetInitalValueForVariable(var_definition_node vdn, expression_node userInitalValue)
|
||
{
|
||
if (userInitalValue == null && CurrentStatementList != null && vdn.type.is_value_type && vdn.type is common_type_node)
|
||
{
|
||
common_type_node ctn = vdn.type as common_type_node;
|
||
foreach (var meth in ctn.methods)
|
||
{
|
||
if (meth.is_constructor && meth.parameters.Count == 0)
|
||
{
|
||
userInitalValue = new common_constructor_call(meth, vdn.location);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
if (userInitalValue != null)
|
||
{
|
||
if (CurrentStatementList != null)
|
||
{
|
||
//Инициализировать надо в текущем стейтменте
|
||
expression_node expr = null;
|
||
location lid = null;
|
||
if (vdn is local_block_variable)
|
||
{
|
||
lid = ((local_block_variable)vdn).loc;
|
||
expr = new local_block_variable_reference((local_block_variable)vdn, lid);
|
||
}
|
||
else if (vdn is class_field)
|
||
{
|
||
lid = vdn.location;
|
||
expr = new class_field_reference(vdn as class_field, new this_node((vdn as class_field).cont_type, lid), lid);
|
||
}
|
||
if (vdn.type.type_special_kind == SemanticTree.type_special_kind.set_type)
|
||
{
|
||
userInitalValue = syntax_tree_visitor.get_init_call_for_set_as_constr(vdn, userInitalValue);
|
||
//userInitalValue.type = SystemLibrary.SystemLibInitializer.TypedSetType.sym_info as type_node;
|
||
}
|
||
else if (vdn.type.type_special_kind == SemanticTree.type_special_kind.short_string)
|
||
{
|
||
userInitalValue = convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibInitializer.ClipShortStringProcedure.sym_info as function_node, null, convertion_data_and_alghoritms.convert_type(userInitalValue, SystemLibrary.SystemLibrary.string_type), new int_const_node((vdn.type as short_string_type_node).Length, null));
|
||
}
|
||
else if (userInitalValue is array_initializer)
|
||
{
|
||
array_initializer arr = userInitalValue as array_initializer;
|
||
if (vdn.type.element_type.type_special_kind == SemanticTree.type_special_kind.short_string)
|
||
{
|
||
for (int i = 0; i < arr.element_values.Count; i++)
|
||
{
|
||
//arr.element_values[i] = syntax_tree_visitor.find_operator(StringConstants.assign_name, varref2, arr.element_values[i], null);
|
||
arr.element_values[i] = convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibInitializer.ClipShortStringProcedure.sym_info as function_node, null, convertion_data_and_alghoritms.convert_type(arr.element_values[i], SystemLibrary.SystemLibrary.string_type), new int_const_node((vdn.type.element_type as short_string_type_node).Length, null));
|
||
}
|
||
}
|
||
}
|
||
CurrentStatementList.statements.AddElement(syntax_tree_visitor.find_operator(StringConstants.assign_name, expr, userInitalValue, lid));
|
||
if (vdn.type.type_special_kind == SemanticTree.type_special_kind.set_type)
|
||
{
|
||
expr.type = SystemLibrary.SystemLibInitializer.TypedSetType.sym_info as type_node;
|
||
}
|
||
if (vdn.type.is_value_type /*&& userInitalValue is common_constructor_call*/ && !(expr is class_field_reference))
|
||
{
|
||
return new default_operator_node(vdn.type, lid);
|
||
}
|
||
return null;
|
||
}
|
||
if (userInitalValue is constant_node)
|
||
{
|
||
if (vdn.type.type_special_kind == SemanticTree.type_special_kind.short_string)
|
||
{
|
||
expression_node varref2 = convertion_data_and_alghoritms.CreateVariableReference(vdn, null);
|
||
userInitalValue = syntax_tree_visitor.find_operator(StringConstants.assign_name, varref2, userInitalValue, null);
|
||
}
|
||
return userInitalValue;
|
||
}
|
||
if (userInitalValue is array_initializer)
|
||
{
|
||
array_initializer arr = userInitalValue as array_initializer;
|
||
if (vdn.type.element_type.type_special_kind == SemanticTree.type_special_kind.short_string)
|
||
{
|
||
expression_node varref2 = convertion_data_and_alghoritms.CreateVariableReference(vdn, null);
|
||
for (int i=0; i<arr.element_values.Count; i++)
|
||
{
|
||
//arr.element_values[i] = syntax_tree_visitor.find_operator(StringConstants.assign_name, varref2, arr.element_values[i], null);
|
||
arr.element_values[i] = convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibInitializer.ClipShortStringProcedure.sym_info as function_node,null,convertion_data_and_alghoritms.convert_type(arr.element_values[i],SystemLibrary.SystemLibrary.string_type),new int_const_node((vdn.type.element_type as short_string_type_node).Length,null));
|
||
}
|
||
}
|
||
return userInitalValue;
|
||
}
|
||
expression_node varref = convertion_data_and_alghoritms.CreateVariableReference(vdn, userInitalValue.location);
|
||
if (vdn.type.type_special_kind == SemanticTree.type_special_kind.set_type)
|
||
{
|
||
userInitalValue = syntax_tree_visitor.get_init_call_for_set_as_constr(vdn,userInitalValue);
|
||
//userInitalValue.type = SystemLibrary.SystemLibInitializer.TypedSetType.sym_info as type_node;
|
||
}
|
||
else if (vdn.type.type_special_kind == SemanticTree.type_special_kind.short_string)
|
||
{
|
||
expression_node cmc = convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibInitializer.ClipShortStringProcedure.sym_info as function_node,null,convertion_data_and_alghoritms.convert_type(userInitalValue,SystemLibrary.SystemLibrary.string_type),new int_const_node((vdn.type as short_string_type_node).Length,null));
|
||
userInitalValue = cmc;
|
||
}
|
||
userInitalValue = syntax_tree_visitor.find_operator(StringConstants.assign_name, varref, userInitalValue, userInitalValue.location);
|
||
if (vdn.type.type_special_kind == SemanticTree.type_special_kind.set_type)
|
||
{
|
||
varref.type = SystemLibrary.SystemLibInitializer.TypedSetType.sym_info as type_node;
|
||
}
|
||
return userInitalValue;
|
||
}
|
||
type_node tp = vdn.type;
|
||
if (syntax_tree_visitor.SystemUnitAssigned && SystemLibrary.SystemLibInitializer.TextFileType.Found && tp.name == StringConstants.text_file_name_type_name)
|
||
if (tp == SystemLibrary.SystemLibInitializer.TextFileType.TypeNode)
|
||
SystemLibrary.SystemLibInitializer.TextFileType.TypeNode.type_special_kind = PascalABCCompiler.SemanticTree.type_special_kind.text_file;
|
||
//(ssyy) Вставил switch и обработку BinaryFile
|
||
switch (tp.type_special_kind)
|
||
{
|
||
case SemanticTree.type_special_kind.typed_file:
|
||
userInitalValue = syntax_tree_visitor.get_init_call_for_typed_file(vdn, tp.element_type);
|
||
break;
|
||
case SemanticTree.type_special_kind.set_type:
|
||
userInitalValue = syntax_tree_visitor.get_init_call_for_set(vdn);
|
||
break;
|
||
case SemanticTree.type_special_kind.binary_file:
|
||
userInitalValue = syntax_tree_visitor.get_init_call_for_binary_file(vdn);
|
||
break;
|
||
case SemanticTree.type_special_kind.text_file:
|
||
userInitalValue = syntax_tree_visitor.get_init_call_for_text_file(vdn);
|
||
break;
|
||
default:
|
||
if (tp is short_string_type_node)
|
||
userInitalValue = SystemLibrary.SystemLibrary.empty_string;//syntax_tree_visitor.get_init_call_for_short_string(vdn);
|
||
else
|
||
if (tp == SystemLibrary.SystemLibrary.string_type && SemanticRulesConstants.InitStringAsEmptyString)
|
||
userInitalValue = SystemLibrary.SystemLibrary.empty_string;
|
||
break;
|
||
}
|
||
return userInitalValue;
|
||
}
|
||
|
||
public SymbolInfo find_first(string name)
|
||
{
|
||
var temp = find(name);
|
||
return temp?.FirstOrDefault();
|
||
}
|
||
|
||
public List<SymbolInfo> find(string name)
|
||
{
|
||
SymbolTable.Scope curscope = CurrentScope;
|
||
if (name == "$yield_element_type")
|
||
{
|
||
if (top_function != null)
|
||
{
|
||
return new List<SymbolInfo> { new SymbolInfo(top_function.return_value_type.instance_params[0]) };
|
||
}
|
||
else
|
||
{
|
||
type_node tn = converted_type.ImplementingInterfaces.Find(x=>(x as type_node).BaseFullName.StartsWith("System.Collections.Generic.IEnumerable")) as type_node;
|
||
return new List<SymbolInfo> { new SymbolInfo(tn.instance_params[0]) };
|
||
}
|
||
}
|
||
|
||
|
||
List<SymbolInfo> sil = curscope.Find(name, curscope);
|
||
List<SymbolInfo> si2 = null;
|
||
if (sil != null && sil.FirstOrDefault().scope is SymbolTable.ClassScope && curscope.TopScope is SymbolTable.BlockScope && curscope.TopScope.TopScope is SymbolTable.ClassMethodScope && ((SymbolTable.ClassMethodScope)curscope.TopScope.TopScope).DefScope is SymbolTable.BlockScope)
|
||
{
|
||
si2 = ((SymbolTable.ClassMethodScope)curscope.TopScope.TopScope).DefScope.Find(name, ((SymbolTable.ClassMethodScope)curscope.TopScope.TopScope).DefScope);
|
||
if (si2 != null && si2.FirstOrDefault().scope is SymbolTable.ClassMethodScope)
|
||
{
|
||
sil = si2;
|
||
}
|
||
}
|
||
|
||
if (sil == null && _compiled_tn != null && curscope.TopScope != null)
|
||
{
|
||
SymbolTable.Scope tmp = curscope.TopScope;
|
||
while (tmp != null && sil == null)
|
||
{
|
||
sil = tmp.Find(name, curscope);
|
||
tmp = tmp.TopScope;
|
||
}
|
||
}
|
||
|
||
// для partial-классов, наследующих от интерфейса в секции Implementation
|
||
// Надо ещё добавить условия чтобы только для них. А то может найти не то что надо!!!
|
||
if (sil == null && this.converted_type != null && this.converted_type.IsPartial)
|
||
{
|
||
sil = this.converted_namespace.scope.Find(name);
|
||
}
|
||
|
||
if (_ctn != null && _ctn.base_generic_instance != null)
|
||
{
|
||
return _ctn.base_generic_instance.ConvertSymbolInfo(sil);
|
||
}
|
||
return sil;
|
||
}
|
||
|
||
public List<SymbolInfo> find_only_in_namespace(string name)
|
||
{
|
||
return CurrentScope.FindOnlyInScope(name);
|
||
}
|
||
|
||
public void leave_interface_part()
|
||
{
|
||
_cmn = null;
|
||
}
|
||
|
||
public void check_all_name_unit_defined(common_unit_node cmn)
|
||
{
|
||
check_predefinition_defined(cmn.namespaces[0]);
|
||
check_predefinition_defined(cmn.namespaces[1]);
|
||
}
|
||
|
||
public void leave_block()
|
||
{
|
||
switch (converting_block())
|
||
{
|
||
case block_type.function_block:
|
||
{
|
||
common_function_node top_func = _func_stack.top();
|
||
location loc;
|
||
if (top_func.function_code == null)
|
||
{
|
||
loc = top_func.loc;
|
||
}
|
||
else if ((top_func.function_code as statements_list) != null)
|
||
{
|
||
statements_list stl = (statements_list)top_func.function_code;
|
||
if (stl.statements.Count > 0)
|
||
{
|
||
loc = stl.statements[stl.statements.Count - 1].location;
|
||
loc = null; //ivan
|
||
}
|
||
else
|
||
{
|
||
loc = top_func.loc;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
loc = top_func.function_code.location;
|
||
}
|
||
if (top_func.function_code != null)
|
||
{
|
||
if (top_func.return_variable != null)
|
||
{
|
||
//TODO: Обратить внимание на преобразования типов. Можно сделать метод, который если тело функции не statement создает список statement-ов и добавляет в него существующий statement.
|
||
statements_list stl = (statements_list)top_func.function_code;
|
||
local_variable_reference lvr = new local_variable_reference(top_func.return_variable, 0, loc);
|
||
stl.statements.AddElement(new return_node(lvr, loc));
|
||
}
|
||
else if ((top_func.return_value_type != null) && (_ctn != null))
|
||
{
|
||
//TODO: Обратить внимание на преобразования типов. Можно сделать метод, который если тело функции не statement создает список statement-ов и добавляет в него существующий statement.
|
||
statements_list stl = (statements_list)top_func.function_code;
|
||
this_node thn = new this_node(_ctn, loc);
|
||
stl.statements.AddElement(new return_node(thn, loc));
|
||
}
|
||
}
|
||
check_predefinition_defined();
|
||
_func_stack.pop();
|
||
break;
|
||
}
|
||
case block_type.type_block:
|
||
{
|
||
if (_cmn.types.IndexOf(_ctn) < 0)
|
||
{
|
||
_cmn.types.AddElement(_ctn);
|
||
}
|
||
//(ssyy) Проверим тип на реализацию функций интерфейсов
|
||
check_predefinition_defined();
|
||
if (_ctn.is_generic_type_definition && !_ctn.IsInterface && _ctn.static_constr == null)
|
||
{
|
||
_ctn.static_constr = new common_method_node(StringConstants.static_ctor_prefix + StringConstants.default_constructor_name, null, _ctn, SemanticTree.polymorphic_state.ps_static, SemanticTree.field_access_level.fal_private, null);
|
||
_ctn.static_constr.is_constructor = true;
|
||
statements_list st = new statements_list(null);
|
||
st.statements.AddElement(new return_node(new null_const_node(SystemLibrary.SystemLibrary.object_type, null), null));
|
||
_ctn.static_constr.function_code = st;
|
||
_ctn.methods.AddElement(_ctn.static_constr);
|
||
}
|
||
_ctn=null;
|
||
break;
|
||
}
|
||
case block_type.namespace_block:
|
||
{
|
||
check_predefinition_defined();
|
||
_cmn=null;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
private base_function_call CreateTypeCheckCall(definition_node func, type_node tp)
|
||
{
|
||
if (func is common_namespace_function_node)
|
||
{
|
||
common_namespace_function_call cnfc = new common_namespace_function_call(
|
||
func as common_namespace_function_node, null);
|
||
expression_node ex = new typeof_operator(tp, null);
|
||
cnfc.parameters.AddElement(ex);
|
||
return cnfc;
|
||
}
|
||
else
|
||
{
|
||
compiled_static_method_call cnfc = new compiled_static_method_call(
|
||
func as compiled_function_node, null);
|
||
expression_node ex = new typeof_operator(tp, null);
|
||
cnfc.parameters.AddElement(ex);
|
||
return cnfc;
|
||
}
|
||
}
|
||
|
||
private void AddTypeCheckToStaticConstructor(common_type_node generic_def)
|
||
{
|
||
statements_list stl = new statements_list(null);
|
||
GenericParameterAbilities gpa;
|
||
foreach (common_type_node param in generic_def.generic_params)
|
||
{
|
||
if (syntax_tree_visitor.generic_param_abilities.TryGetValue(param, out gpa))
|
||
{
|
||
if (gpa.useful_for_pointers)
|
||
{
|
||
stl.statements.AddElement(CreateTypeCheckCall(SystemLibrary.SystemLibInitializer.CheckCanUsePointerOnTypeProcedure.sym_info, param));
|
||
}
|
||
if (gpa.useful_for_binary_files)
|
||
{
|
||
stl.statements.AddElement(CreateTypeCheckCall(SystemLibrary.SystemLibInitializer.CheckCanUseTypeForBinaryFilesProcedure.sym_info, param));
|
||
}
|
||
if (gpa.useful_for_typed_files)
|
||
{
|
||
stl.statements.AddElement(CreateTypeCheckCall(SystemLibrary.SystemLibInitializer.CheckCanUseTypeForTypedFilesProcedure.sym_info, param));
|
||
}
|
||
}
|
||
if (SemanticRulesConstants.RuntimeInitVariablesOfGenericParameters)
|
||
{
|
||
basic_function_call bfc = new basic_function_call(
|
||
SystemLibrary.SystemLibrary.byte_assign as basic_function_node, null);
|
||
bfc.parameters.AddElement(new static_class_field_reference(param.runtime_initialization_marker, null));
|
||
base_function_call dcall = null;
|
||
if (SystemLibrary.SystemLibInitializer.RuntimeDetermineTypeFunction.sym_info is common_namespace_function_node)
|
||
dcall = new common_namespace_function_call(
|
||
SystemLibrary.SystemLibInitializer.RuntimeDetermineTypeFunction.sym_info as common_namespace_function_node, null);
|
||
else
|
||
dcall = new compiled_static_method_call(
|
||
SystemLibrary.SystemLibInitializer.RuntimeDetermineTypeFunction.sym_info as compiled_function_node, null);
|
||
dcall.parameters.AddElement(new typeof_operator(param, null));
|
||
bfc.parameters.AddElement(dcall);
|
||
stl.statements.AddElement(bfc);
|
||
}
|
||
}
|
||
if (stl.statements.Count == 0) return;
|
||
string stat_ctor_name = StringConstants.static_ctor_prefix + StringConstants.default_constructor_name;
|
||
List<SymbolInfo> sil = generic_def.scope.FindOnlyInScope(stat_ctor_name);
|
||
common_method_node stat_ctor;
|
||
if (sil == null)
|
||
{
|
||
if (generic_def.static_constr != null)
|
||
stat_ctor = generic_def.static_constr;
|
||
else
|
||
{
|
||
stat_ctor = new common_method_node(stat_ctor_name, null, null, generic_def,
|
||
SemanticTree.polymorphic_state.ps_static, SemanticTree.field_access_level.fal_public, null);
|
||
stat_ctor.is_constructor = true;
|
||
generic_def.add_name(stat_ctor_name, new SymbolInfo(stat_ctor));
|
||
generic_def.methods.AddElement(stat_ctor);
|
||
}
|
||
|
||
}
|
||
else
|
||
{
|
||
stat_ctor = sil.FirstOrDefault().sym_info as common_method_node;
|
||
}
|
||
if (stat_ctor.function_code != null)
|
||
{
|
||
stl.statements.AddElement(stat_ctor.function_code);
|
||
}
|
||
else
|
||
{
|
||
stl.statements.AddElement(new return_node(null, null));
|
||
}
|
||
stat_ctor.function_code = stl;
|
||
}
|
||
|
||
public SymbolInfo last_created_function
|
||
{
|
||
get
|
||
{
|
||
return _last_created_function;
|
||
}
|
||
set
|
||
{
|
||
_last_created_function = value;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Возвращает true-уникальная, false-предописанная
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
public bool close_function_params(bool body_exists)
|
||
{
|
||
if (body_exists)
|
||
{
|
||
//add_overloads_for_default_parameter();
|
||
return close_function_params_with_body();
|
||
}
|
||
else
|
||
{
|
||
close_function_params_without_body();
|
||
return true;
|
||
}
|
||
}
|
||
|
||
private void add_overloads_for_default_parameter()
|
||
{
|
||
List<parameter> default_params = new List<parameter>();
|
||
foreach (parameter p in top_function.parameters)
|
||
{
|
||
if (p.default_value != null)
|
||
{
|
||
default_params.Add(p);
|
||
}
|
||
}
|
||
int num_of_defaults = default_params.Count-1;
|
||
if (default_params.Count > 0 && converted_func_stack.size == 1)
|
||
while (num_of_defaults >= 0)
|
||
{
|
||
|
||
if (converted_type == null)
|
||
{
|
||
common_namespace_function_node cnfn = new common_namespace_function_node(top_function.name, top_function.return_value_type, null, converted_namespace, null);
|
||
foreach (parameter p in top_function.parameters)
|
||
{
|
||
if (p.default_value == null)
|
||
cnfn.parameters.AddElement(p);
|
||
}
|
||
for (int i = 0; i < num_of_defaults; i++)
|
||
cnfn.parameters.AddElement(default_params[i]);
|
||
statements_list sl = new statements_list(null);
|
||
common_namespace_function_call cnfc = new common_namespace_function_call(top_function as common_namespace_function_node, null);
|
||
foreach (common_parameter p in cnfn.parameters)
|
||
{
|
||
cnfc.parameters.AddElement(new common_parameter_reference(p, 0, null));
|
||
}
|
||
for (int i = num_of_defaults; i < default_params.Count; i++)
|
||
cnfc.parameters.AddElement(default_params[i].default_value);
|
||
if (cnfn.return_value_type != null)
|
||
sl.statements.AddElement(new return_node(cnfc, null));
|
||
else
|
||
sl.statements.AddElement(cnfc);
|
||
cnfn.function_code = sl;
|
||
converted_namespace.functions.AddElement(cnfn);
|
||
}
|
||
else
|
||
{
|
||
common_method_node cmn = top_function as common_method_node;
|
||
common_method_node cnfn = new common_method_node(top_function.name, top_function.return_value_type, null, converted_type, top_function.polymorphic_state, top_function.field_access_level, null);
|
||
foreach (parameter p in top_function.parameters)
|
||
{
|
||
if (p.default_value == null)
|
||
cnfn.parameters.AddElement(p);
|
||
}
|
||
for (int i = 0; i < num_of_defaults; i++)
|
||
cnfn.parameters.AddElement(default_params[i]);
|
||
statements_list sl = new statements_list(null);
|
||
common_method_call cnfc = new common_method_call(cmn, (cnfn.polymorphic_state != SemanticTree.polymorphic_state.ps_static) ? new this_node(converted_type, null) : null, null);
|
||
foreach (common_parameter p in cnfn.parameters)
|
||
{
|
||
cnfc.parameters.AddElement(new common_parameter_reference(p, 0, null));
|
||
}
|
||
for (int i = num_of_defaults; i < default_params.Count; i++)
|
||
cnfc.parameters.AddElement(default_params[i].default_value);
|
||
if (cnfn.return_value_type != null)
|
||
sl.statements.AddElement(new return_node(cnfc, null));
|
||
else
|
||
sl.statements.AddElement(cnfc);
|
||
cnfn.function_code = sl;
|
||
cnfn.is_constructor = cmn.is_constructor;
|
||
converted_type.methods.AddElement(cnfn);
|
||
}
|
||
num_of_defaults--;
|
||
}
|
||
}
|
||
|
||
private void close_function_params_without_body()
|
||
{
|
||
check_function_not_exists(_func_stack.top());
|
||
}
|
||
|
||
/// <summary>
|
||
/// Вызывает check_unique_or_predefined(top_function). Возвращает true-уникальная, false-предописанная
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
private bool close_function_params_with_body()
|
||
{
|
||
return check_unique_or_predefined(_func_stack.top());
|
||
}
|
||
|
||
private List<string> CurrentHandlerList=null;
|
||
|
||
private Stack<List<string>> CurrentHandlerListStack = new Stack<List<string>>();
|
||
|
||
public void enter_exception_handlers()
|
||
{
|
||
CurrentHandlerListStack.Push(CurrentHandlerList);
|
||
CurrentHandlerList = new List<string>();
|
||
}
|
||
|
||
public void leave_exception_handlers()
|
||
{
|
||
CurrentHandlerList = CurrentHandlerListStack.Pop();
|
||
}
|
||
|
||
public void check_name_free(string name,SemanticTree.ILocation name_loc)
|
||
{
|
||
List<SymbolInfo> sil=find_only_in_namespace(name);
|
||
if (sil==null)
|
||
{
|
||
if (!check_name_redefinition)
|
||
CurrentHandlerList.Add(name);
|
||
return;
|
||
}
|
||
if (!check_name_redefinition)
|
||
if (CurrentHandlerList.Contains(name, CurrentScope.CaseSensitive ? StringComparer.Ordinal : StringComparer.OrdinalIgnoreCase))
|
||
return;
|
||
location first_loc=convertion_data_and_alghoritms.get_location(sil.FirstOrDefault().sym_info);
|
||
//TODO: Можно передавать список всех повторных объявлений.
|
||
if (converting_block() == block_type.type_block && (name.ToLower().StartsWith("get_") || name.ToLower().StartsWith("set_")))
|
||
AddError(name_loc as location, "CANNOT_USE_RESERVED_ACCESSOR_NAMES");
|
||
else
|
||
AddError(new NameRedefinition(name, first_loc, name_loc));
|
||
}
|
||
|
||
//ssyy
|
||
public common_type_node check_type_name_free_and_predop(string name, SemanticTree.ILocation name_loc, ref common_type_node partial_class, bool is_partial=false)
|
||
{
|
||
List<SymbolInfo> sil = find_only_in_namespace(name);
|
||
if (sil == null)
|
||
{
|
||
if (is_partial)
|
||
{
|
||
sil = find(name);
|
||
if (sil != null)
|
||
{
|
||
List<common_type_node> ctn_list = new List<common_type_node>();
|
||
foreach(SymbolInfo si in sil)
|
||
{
|
||
if (si.sym_info is common_type_node && (si.sym_info as common_type_node).IsPartial)
|
||
ctn_list.Add(si.sym_info as common_type_node);
|
||
}
|
||
common_type_node first_ctn = null;
|
||
if (ctn_list.Count > 0)
|
||
first_ctn = ctn_list[0];
|
||
|
||
for (int i = 1; i < ctn_list.Count; i++)
|
||
{
|
||
ctn_list[i - 1].scope.PartialScope = ctn_list[i].scope;
|
||
first_ctn.Merge(ctn_list[i]);
|
||
}
|
||
partial_class = first_ctn;
|
||
return null;
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
common_type_node cnode = sil.FirstOrDefault().sym_info as common_type_node;
|
||
if (cnode != null && cnode.ForwardDeclarationOnly)
|
||
{
|
||
//cnode.ForwardDeclarationOnly = false;
|
||
return cnode;
|
||
}
|
||
|
||
if (cnode != null && is_partial && cnode.IsPartial)
|
||
{
|
||
return cnode;
|
||
}
|
||
location first_loc = convertion_data_and_alghoritms.get_location(sil.FirstOrDefault().sym_info);
|
||
AddError(new NameRedefinition(name, first_loc, name_loc));
|
||
return null;
|
||
}
|
||
//\ssyy
|
||
|
||
|
||
private bool is_predefinition(common_function_node predef, common_function_node def, bool error_on_false)
|
||
{
|
||
if (convertion_data_and_alghoritms.function_eq_params(predef,def))
|
||
{
|
||
for(int param_num=0;param_num<def.parameters.Count;param_num++)
|
||
{
|
||
int res=SystemLibrary.SystemLibrary.string_comparer.Compare(def.parameters[param_num].name,
|
||
predef.parameters[param_num].name);
|
||
if (res!=0)
|
||
{
|
||
AddError(((common_parameter)def.parameters[param_num]).loc,
|
||
"DIFFERENT_PARAMETER_NAME_IN_FUNCTION_DEFINITION_{0}_AND_PREDEFINITION_{1}",
|
||
((common_parameter)def.parameters[param_num]).name,
|
||
((common_parameter)predef.parameters[param_num]).name
|
||
);
|
||
}
|
||
if(predef.parameters[param_num].parameter_type!=def.parameters[param_num].parameter_type)
|
||
AddError(def.loc, "FUNCTION_DEFINITION_HAVE_DIFFERENT_PARAMS_WITH_PREDEFINITION");
|
||
}
|
||
return true;
|
||
}
|
||
if (error_on_false)
|
||
{
|
||
if (def is common_namespace_function_node && (def as common_namespace_function_node).ConnectedToType != null && predef is common_method_node)
|
||
{
|
||
return false;
|
||
}
|
||
AddError(def.loc, "FUNCTION_DEFINITION_HAVE_DIFFERENT_PARAMS_WITH_PREDEFINITION");
|
||
}
|
||
return false;
|
||
}
|
||
|
||
private void check_predefinition_defined(common_namespace_node cnn)
|
||
{
|
||
foreach (common_function_node cfn in cnn.functions)
|
||
if (cfn.function_code == null)
|
||
{
|
||
//AddError(cfn.loc, "FUNCTION_PREDEFINITION_WITHOUT_DEFINITION");
|
||
AddError(new FunctionPredefinitionWithoutDefinition(cfn, cfn.loc));
|
||
}
|
||
|
||
foreach (common_type_node ctn in cnn.types)
|
||
{
|
||
//(ssyy) Для интерфейсов не проверяем
|
||
if (!ctn.IsInterface)
|
||
{
|
||
foreach (common_method_node cmn in ctn.methods)
|
||
if (cmn.function_code == null && cmn.polymorphic_state != SemanticTree.polymorphic_state.ps_virtual_abstract)
|
||
AddError(new FunctionPredefinitionWithoutDefinition(cmn, cmn.loc));
|
||
//AddError(cmn.loc, "FUNCTION_PREDEFINITION_WITHOUT_DEFINITION");
|
||
}
|
||
}
|
||
}
|
||
|
||
private void check_implement_abstract_function(common_type_node cnode, function_node meth, type_node interf)
|
||
{
|
||
//if (meth.field_access_level == SemanticTree.field_access_level.fal_private)
|
||
// return;
|
||
List<SymbolInfo> sil = cnode.find_in_type(meth.name, cnode.Scope);
|
||
if (meth.field_access_level == SemanticTree.field_access_level.fal_private)
|
||
{
|
||
var base_type = cnode.base_type;
|
||
while (base_type != null && base_type.IsAbstract)
|
||
{
|
||
base_type = base_type.base_type;
|
||
}
|
||
if (base_type != null && !base_type.IsAbstract && base_type != SystemLibrary.SystemLibrary.object_type)
|
||
return;
|
||
}
|
||
function_node fn = null;
|
||
if (sil != null)
|
||
{
|
||
foreach (var si in sil)
|
||
{
|
||
if (si.sym_info.general_node_type == general_node_type.function_node)
|
||
{
|
||
fn = si.sym_info as function_node;
|
||
//Сверяем параметры и тип возвращаемого значения
|
||
if (convertion_data_and_alghoritms.function_eq_params_and_result(meth, fn))
|
||
{
|
||
//Нашли нужную функцию
|
||
if (meth == fn || fn is common_method_node && (fn as common_method_node).overrided_method == null)
|
||
sil = null;
|
||
break;
|
||
}
|
||
}
|
||
//Переходим к следующей функции-кандидату
|
||
}
|
||
}
|
||
if (sil == null)
|
||
{
|
||
cnode.SetIsAbstract(true,
|
||
(meth is common_method_node cmn) && (cmn.cont_type.properties.FirstOrDefault(cpn=> meth.name == "get_" + cpn.name || meth.name == "set_" + cpn.name) is common_property_node prop)?
|
||
new CARPropertieNotImplemented(prop) :
|
||
new CARMethodNotImplemented(meth) as ClassAbstractReason
|
||
);
|
||
return;
|
||
//Нет функции с таким именем, набором параметров и возвращаемым значением
|
||
//AddError(new AbstractMemberNotImplemented(cnode.name, interf.name, Tools.GetFullMethodHeaderString(meth), cnode.is_value_type, cnode.loc));
|
||
}
|
||
//Теперь проверяем на public и non-static
|
||
bool bad = false;
|
||
common_method_node commn = sil.FirstOrDefault().sym_info as common_method_node;
|
||
compiled_function_node compn = sil.FirstOrDefault().sym_info as compiled_function_node;
|
||
SemanticTree.polymorphic_state pstate = SemanticTree.polymorphic_state.ps_static;
|
||
//Проверка пройдена!
|
||
|
||
if (commn != null && commn.common_comprehensive_type == cnode)
|
||
{
|
||
//Найденная функция описана в самом классе.
|
||
if (commn.polymorphic_state == SemanticTree.polymorphic_state.ps_common)
|
||
{
|
||
//Делаем её virtual final
|
||
commn.is_final = true;
|
||
commn.newslot_awaited = true;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
//Найденная функция описана в каком-то предке класса
|
||
//Генерируем новую newslot virtual final функцию, вызывающую ту.
|
||
if (pstate == SemanticTree.polymorphic_state.ps_common)
|
||
{
|
||
syntax_tree_visitor.generate_inherited_from_base_and_interface_function(cnode, fn);
|
||
}
|
||
}
|
||
}
|
||
|
||
//Проверка типа на наличие функции из интерфейса
|
||
private void check_implement_function(common_type_node cnode, function_node meth, type_node interf)
|
||
{
|
||
//Ищем все функции с нужным именем в типе и его предках
|
||
List<SymbolInfo> sil = cnode.find_in_type(meth.name, cnode.Scope);
|
||
List<SymbolInfo> tmp_si = null;
|
||
if (meth is compiled_function_node)
|
||
tmp_si = cnode.find_in_type((meth as compiled_function_node).cont_type.BaseFullName + "." + meth.name, cnode.Scope);
|
||
else if (meth is common_method_node)
|
||
{
|
||
string base_type_name = (meth as common_method_node).cont_type.BaseFullName;
|
||
if (base_type_name != null && (meth as common_method_node).cont_type.original_generic != null && base_type_name.IndexOf('<') != -1)
|
||
base_type_name = (meth as common_method_node).cont_type.original_generic.BaseFullName;
|
||
tmp_si = cnode.find_in_type(base_type_name + "." + meth.name, cnode.Scope);
|
||
}
|
||
|
||
if (tmp_si != null)
|
||
{
|
||
/*Зачем это?
|
||
* SymbolInfo tmp_si2 = tmp_si;
|
||
while (tmp_si2.Next != null)
|
||
tmp_si2 = tmp_si2.Next;*/
|
||
if (sil != null)
|
||
sil.Insert(0, tmp_si.FirstOrDefault());
|
||
else
|
||
{
|
||
sil = tmp_si;
|
||
//sil.RemoveRange(1, sil.Count() - 1);
|
||
}
|
||
}
|
||
|
||
function_node fn = null;
|
||
SymbolInfo find_method = null;
|
||
if (sil != null) {
|
||
foreach (SymbolInfo si in sil)
|
||
{
|
||
if (si.sym_info.general_node_type == general_node_type.function_node)
|
||
{
|
||
if (si.sym_info is common_method_node && (si.sym_info as common_method_node).cont_type == interf)
|
||
continue;
|
||
fn = si.sym_info as function_node;
|
||
//Сверяем параметры и тип возвращаемого значения
|
||
if (convertion_data_and_alghoritms.function_eq_params_and_result(meth, fn, true) /*&& fn.polymorphic_state != SemanticTree.polymorphic_state.ps_virtual_abstract*/)
|
||
{
|
||
//Нашли нужную функцию
|
||
common_method_node fn_common = fn as common_method_node;
|
||
if (fn_common != null)
|
||
{
|
||
if (fn_common.name_case_fixed)
|
||
{
|
||
if (fn_common.name != meth.name)
|
||
{
|
||
// SSM 21.12.19 - закомментировал - исправляет баг #2163. Не пойму, зачем эта проверка
|
||
//syntax_tree_visitor.AddError(fn_common.loc, "AMBIGUITY_BETWEEN_NAMES_{0}_AND_{1}", fn_common.name, meth.name);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (fn_common.name.IndexOf('.') == -1)
|
||
fn_common.SetName(meth.name);
|
||
fn_common.name_case_fixed = true;
|
||
}
|
||
|
||
}
|
||
find_method = si;
|
||
break;
|
||
}
|
||
}
|
||
//Переходим к следующей функции-кандидату
|
||
}
|
||
}
|
||
|
||
if (find_method == null)
|
||
{
|
||
//Нет функции с таким именем, набором параметров и возвращаемым значением
|
||
AddError(new InterfaceMemberNotImplemented(cnode.PrintableName, interf.PrintableName, Tools.GetFullMethodHeaderString(meth), cnode.is_value_type, cnode.loc));
|
||
}
|
||
|
||
//Теперь проверяем на public и non-static
|
||
bool bad = false;
|
||
common_method_node commn = find_method.sym_info as common_method_node;
|
||
compiled_function_node compn = find_method.sym_info as compiled_function_node;
|
||
SemanticTree.polymorphic_state pstate = SemanticTree.polymorphic_state.ps_static;
|
||
if (commn != null)
|
||
{
|
||
pstate = commn.polymorphic_state;
|
||
if (commn.polymorphic_state == SemanticTree.polymorphic_state.ps_static ||
|
||
commn.field_access_level != SemanticTree.field_access_level.fal_public ||
|
||
commn.is_constructor)
|
||
{
|
||
if (!(commn.name.IndexOf(".") != -1 && commn.field_access_level != SemanticTree.field_access_level.fal_public))
|
||
bad = true;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (compn != null)
|
||
{
|
||
pstate = compn.polymorphic_state;
|
||
if (compn.polymorphic_state == SemanticTree.polymorphic_state.ps_static ||
|
||
compn.field_access_level != SemanticTree.field_access_level.fal_public)
|
||
{
|
||
bad = true;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
//Сюда заходить не должны
|
||
bad = true;
|
||
}
|
||
}
|
||
if (bad)
|
||
{
|
||
AddError(new DerivedFromInterfaceMethodMustBePublicAndNonStatic(
|
||
cnode.name, interf.name,
|
||
Tools.GetFullMethodHeaderString(meth), cnode.is_value_type, cnode.loc));
|
||
}
|
||
//Проверка пройдена!
|
||
|
||
if (commn != null && commn.common_comprehensive_type == cnode)
|
||
{
|
||
//Найденная функция описана в самом классе.
|
||
if (commn.polymorphic_state == SemanticTree.polymorphic_state.ps_common)
|
||
{
|
||
//Делаем её virtual final
|
||
commn.is_final = true;
|
||
commn.newslot_awaited = true;
|
||
if (commn.name.IndexOf('.') != -1)
|
||
commn.overrided_method = meth;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
//Найденная функция описана в каком-то предке класса
|
||
//Генерируем новую newslot virtual final функцию, вызывающую ту.
|
||
if (pstate == SemanticTree.polymorphic_state.ps_common)
|
||
{
|
||
syntax_tree_visitor.generate_inherited_from_base_and_interface_function(cnode, fn);
|
||
}
|
||
}
|
||
}
|
||
|
||
//Проверка типа на соответствие заявленным интерфейсам
|
||
public void check_implement_interfaces()//common_type_node cnode)
|
||
{
|
||
//Переводим контекст в состояние разбора класса cnode
|
||
//_ctn = cnode;
|
||
common_type_node cnode = _ctn;
|
||
foreach (type_node interf in cnode.ImplementingInterfaces)
|
||
{
|
||
generic_instance_type_node gitn = interf as generic_instance_type_node;
|
||
if (gitn != null)
|
||
{
|
||
List<function_node> gitn_meths = gitn.all_methods;
|
||
foreach (function_node gitn_meth in gitn_meths)
|
||
{
|
||
check_implement_function(cnode, gitn_meth, interf);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
common_type_node cint = interf as common_type_node;
|
||
if (cint != null)
|
||
{
|
||
foreach (common_method_node meth in cint.methods)
|
||
{
|
||
check_implement_function(cnode, meth, interf);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
compiled_type_node compiled_interf = interf as compiled_type_node;
|
||
#if (DEBUG)
|
||
if (compiled_interf == null)
|
||
{
|
||
throw new CompilerInternalError("Unknown interface type.");
|
||
}
|
||
#endif
|
||
System.Reflection.MemberInfo[] interf_members = compiled_interf.compiled_type.GetMembers();
|
||
foreach (System.Reflection.MemberInfo mi in interf_members)
|
||
{
|
||
if (mi.MemberType == System.Reflection.MemberTypes.Method)
|
||
{
|
||
compiled_function_node cmeth = compiled_function_node.get_compiled_method((System.Reflection.MethodInfo)mi);
|
||
check_implement_function(cnode, cmeth, interf);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
//(ssyy) Дальше, как я понимаю, вставлена проверка на реализацию
|
||
//абстрактных функций базового класса.
|
||
if (_ctn.base_type != null)
|
||
{
|
||
type_node tn = _ctn.base_type;
|
||
while (tn != null)
|
||
{
|
||
common_type_node cint = tn as common_type_node;
|
||
|
||
if (cint != null)
|
||
{
|
||
if (_ctn.IsAbstract) return;
|
||
if (_ctn.IsStatic) return;
|
||
|
||
if (cint is common_generic_instance_type_node cgnn)
|
||
{
|
||
foreach (common_method_node meth in cgnn.base_generic_instance.all_methods)
|
||
{
|
||
if (meth.polymorphic_state == SemanticTree.polymorphic_state.ps_virtual_abstract)
|
||
check_implement_abstract_function(cnode, meth, cgnn.base_generic_instance);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
foreach (common_method_node meth in cint.methods)
|
||
{
|
||
if (meth.polymorphic_state == SemanticTree.polymorphic_state.ps_virtual_abstract)
|
||
check_implement_abstract_function(cnode, meth, cint);
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
compiled_type_node compiled_interf = tn as compiled_type_node;
|
||
#if (DEBUG)
|
||
if (compiled_interf == null)
|
||
{
|
||
throw new CompilerInternalError("Unknown interface type.");
|
||
}
|
||
#endif
|
||
System.Reflection.MemberInfo[] interf_members = compiled_interf.compiled_type.GetMembers(System.Reflection.BindingFlags.Public|System.Reflection.BindingFlags.NonPublic|System.Reflection.BindingFlags.Instance);
|
||
foreach (System.Reflection.MemberInfo mi in interf_members)
|
||
{
|
||
if (mi.MemberType == System.Reflection.MemberTypes.Method)
|
||
{
|
||
compiled_function_node cmeth = compiled_function_node.get_compiled_method((System.Reflection.MethodInfo)mi);
|
||
if (cmeth.polymorphic_state == SemanticTree.polymorphic_state.ps_virtual_abstract && !cmeth.IsSpecialName)
|
||
check_implement_abstract_function(cnode, cmeth, tn);
|
||
}
|
||
else if (mi.MemberType == System.Reflection.MemberTypes.Property)
|
||
{
|
||
/*compiled_property_node cmeth = compiled_property_node.get_compiled_method((System.Reflection.PropertyInfo)mi);
|
||
if (cmeth.polymorphic_state == SemanticTree.polymorphic_state.ps_virtual_abstract)
|
||
check_implement_function(cnode, cmeth, _ctn.base_type);*/
|
||
}
|
||
}
|
||
}
|
||
tn = tn.base_type;
|
||
}
|
||
}
|
||
//Доразбор класса окончен
|
||
//_ctn = null;
|
||
}
|
||
|
||
public void check_predefinition_defined()
|
||
{
|
||
switch(converting_block())
|
||
{
|
||
case block_type.function_block:
|
||
{
|
||
foreach(common_function_node cfn in _func_stack.top().functions_nodes_list)
|
||
{
|
||
if (cfn.function_code==null)
|
||
{
|
||
//AddError(cfn.loc, "FUNCTION_PREDEFINITION_WITHOUT_DEFINITION");
|
||
AddError(new FunctionPredefinitionWithoutDefinition(cfn, cfn.loc));
|
||
}
|
||
}
|
||
check_labels(_func_stack.top().label_nodes_list);
|
||
break;
|
||
}
|
||
case block_type.namespace_block:
|
||
{
|
||
//(ssyy) Добавил условие
|
||
if (!_cmn.predefinitions_checked)
|
||
{
|
||
foreach (common_function_node cfn in _cmn.functions)
|
||
{
|
||
if (cfn.function_code == null)
|
||
{
|
||
AddError(new FunctionPredefinitionWithoutDefinition(cfn, cfn.loc));
|
||
//AddError(cfn.loc, "FUNCTION_PREDEFINITION_WITHOUT_DEFINITION");
|
||
}
|
||
}
|
||
foreach (common_type_node ctn in _cmn.types)
|
||
{
|
||
//ssyy
|
||
if (!ctn.IsInterface)
|
||
{
|
||
//\ssyy
|
||
foreach (common_method_node cmn in ctn.methods)
|
||
{
|
||
if (cmn.function_code == null && cmn.polymorphic_state != SemanticTree.polymorphic_state.ps_virtual_abstract)
|
||
{
|
||
//AddError(cmn.loc, "FUNCTION_PREDEFINITION_WITHOUT_DEFINITION");
|
||
AddError(new FunctionPredefinitionWithoutDefinition(cmn, cmn.loc));
|
||
}
|
||
}
|
||
}
|
||
if (ctn.is_generic_type_definition && !ctn.IsInterface && !ctn.IsDelegate)
|
||
{
|
||
AddTypeCheckToStaticConstructor(ctn);
|
||
}
|
||
}
|
||
_cmn.predefinitions_checked = true;
|
||
}
|
||
break;
|
||
}
|
||
case block_type.type_block:
|
||
{
|
||
//ssyy
|
||
//Проверяем, что тип реализует заявленные интерфейсы.
|
||
if (!_ctn.IsInterface)
|
||
{
|
||
check_implement_interfaces();//_ctn);
|
||
}
|
||
//\ssyy
|
||
break;
|
||
}
|
||
default:
|
||
{
|
||
throw new CompilerInternalError("Undefined block type");
|
||
}
|
||
}
|
||
}
|
||
|
||
public void check_abstracts_implemented(List<common_type_node> types)
|
||
{
|
||
foreach (common_type_node ctn in types)
|
||
{
|
||
_ctn = ctn;
|
||
check_implement_interfaces();
|
||
_ctn = null;
|
||
if (ctn.IsSealed && ctn.IsAbstract && !ctn.IsStatic)
|
||
if (ctn.AbstractReason == null)
|
||
AddError(ctn.loc, "ABSTRACT_CLASS_CANNOT_BE_SEALED");
|
||
else
|
||
AddError(ctn.loc, ctn.AbstractReason.Explanation, ctn.name, ctn.AbstractReason.ObjName);
|
||
|
||
}
|
||
}
|
||
|
||
//ssyy
|
||
public void check_labels(List<label_node> lab_list)
|
||
{
|
||
foreach (label_node ln in lab_list)
|
||
{
|
||
if (!ln.is_defined && ln.goto_statements.Count > 0)
|
||
{
|
||
//(ssyy) Метка не поставлена, но есть goto на неё.
|
||
AddError(ln.goto_statements[0].location, "NO_LABEL_{0}_DEFINITION", ln.name);
|
||
}
|
||
}
|
||
}
|
||
|
||
//\ssyy
|
||
|
||
//(ssyy) "Я" бывают разные :)
|
||
|
||
//Я хочу модифицировать этот метод так, чтобы в случае предописания наличия метода
|
||
//он не выкидывал исключение, а понимал все правильно
|
||
//Этот метод вызывается только для функций с телом
|
||
|
||
/// <summary>
|
||
/// Ищет предописание функции, производя необходимые проверки. Возвращает true-уникальная, false-предописанная
|
||
/// </summary>
|
||
/// <param name="fn">Проверяемая функция</param>
|
||
/// <returns></returns>
|
||
private bool check_unique_or_predefined(common_function_node fn)
|
||
{
|
||
List<SymbolInfo> si_list = null;
|
||
bool in_unit = false;
|
||
if (_func_stack.size <= 1)
|
||
{
|
||
if (_explicit_interface_type != null)
|
||
{
|
||
si_list = _explicit_interface_type.find_in_type(fn.name);
|
||
}
|
||
else if (_ctn != null)
|
||
{
|
||
si_list = _ctn.Scope.FindOnlyInScope(fn.name);
|
||
if (_ctn is compiled_generic_instance_type_node && fn is common_namespace_function_node)
|
||
{
|
||
si_list = (_ctn as compiled_generic_instance_type_node).compiled_original_generic.find_in_type(fn.name);
|
||
if (si_list != null)
|
||
{
|
||
foreach (var tmp_si in si_list)
|
||
{
|
||
if (tmp_si.sym_info.general_node_type != general_node_type.function_node)
|
||
{
|
||
TreeRealization.BasePCUReader.RestoreSymbols(si_list, fn.name);
|
||
}
|
||
common_namespace_function_node cnfn = tmp_si.sym_info as common_namespace_function_node;
|
||
if (cnfn != null)
|
||
{
|
||
if (cnfn.namespace_node == (fn as common_namespace_function_node).namespace_node)
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
if (_ctn.type_special_kind == SemanticTree.type_special_kind.array_kind && _ctn.element_type.is_generic_parameter)
|
||
{
|
||
var arr_types = type_constructor.instance.get_generic_arrays(_ctn.rank);
|
||
foreach (var ctn in arr_types)
|
||
{
|
||
var addit_si_list = ctn.Scope.FindOnlyInScope(fn.name);
|
||
if (addit_si_list != null)
|
||
si_list.AddRange(addit_si_list);
|
||
}
|
||
|
||
}
|
||
}
|
||
else if (_compiled_tn != null)
|
||
{
|
||
si_list = _compiled_tn.find_in_type(fn.name);
|
||
}
|
||
else if (fn is common_namespace_function_node && (fn as common_namespace_function_node).ConnectedToType != null)
|
||
{
|
||
si_list = (fn as common_namespace_function_node).ConnectedToType.find_in_type(fn.name);
|
||
}
|
||
else
|
||
{
|
||
in_unit = true;
|
||
si_list = _cmn.scope.FindOnlyInScope(fn.name);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
common_function_node temp = _func_stack.pop();
|
||
si_list = _func_stack.top().scope.FindOnlyInScope(fn.name);
|
||
_func_stack.push(temp);
|
||
}
|
||
bool predef_find = false;
|
||
int overloads = 0;
|
||
if (si_list != null)
|
||
foreach (var tmp_si in si_list)
|
||
{
|
||
if (tmp_si.sym_info != fn && !(si_list != null && si_list.FirstOrDefault().sym_info is basic_function_node))
|
||
overloads++;
|
||
}
|
||
if (si_list != null)
|
||
foreach (var tmp_si in si_list)
|
||
{
|
||
if (tmp_si.sym_info == fn)
|
||
{
|
||
|
||
continue;
|
||
}
|
||
if (tmp_si.sym_info.general_node_type != general_node_type.function_node)
|
||
{
|
||
TreeRealization.BasePCUReader.RestoreSymbols(si_list, fn.name);
|
||
}
|
||
if (tmp_si.sym_info.general_node_type != general_node_type.function_node)
|
||
AddError(new FunctionNameIsUsedToDefineSomethigElse(fn.loc, tmp_si.sym_info));
|
||
if (tmp_si.sym_info is basic_function_node || tmp_si.sym_info is compiled_function_node)
|
||
{
|
||
continue;
|
||
}
|
||
//compar - найденная функция
|
||
common_function_node compar = ((common_function_node)(tmp_si.sym_info));
|
||
|
||
//Проверяем, если мы нашли не предописание
|
||
if (compar.function_code != null || is_order_independed_method_description)
|
||
{
|
||
if (compar.is_overload == false)
|
||
{
|
||
AddError(new FunctionMustBeWithOverloadDirective(compar, fn));
|
||
}
|
||
if (convertion_data_and_alghoritms.function_eq_params(fn, compar, false) && fn.is_extension_method == compar.is_extension_method)
|
||
{
|
||
if (fn.IsOperator && (fn.name == StringConstants.explicit_operator_name || fn.name == StringConstants.implicit_operator_name))
|
||
{
|
||
if (convertion_data_and_alghoritms.function_eq_params_and_result(fn, compar))
|
||
AddError(new FunctionDuplicateDefinition(compar, fn));
|
||
}
|
||
else
|
||
{
|
||
if (fn is common_method_node && compar is common_method_node)
|
||
{
|
||
common_method_node cmn1 = fn as common_method_node;
|
||
common_method_node cmn2 = compar as common_method_node;
|
||
if (cmn1.explicit_interface == cmn2.explicit_interface)
|
||
AddError(new FunctionDuplicateDefinition(compar, fn));
|
||
}
|
||
else
|
||
{
|
||
AddError(new FunctionDuplicateDefinition(compar, fn));
|
||
}
|
||
}
|
||
}
|
||
continue;
|
||
}
|
||
|
||
bool is_find_predefinition = false;
|
||
|
||
if (compar.is_overload == false || overloads == 1 && in_unit)
|
||
{
|
||
//Если нет параметров в описании тела функции
|
||
if (fn.parameters.Count == 0)
|
||
{
|
||
|
||
is_find_predefinition = true;
|
||
}
|
||
else
|
||
{
|
||
is_find_predefinition = is_predefinition(compar, fn, true);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
is_find_predefinition = is_predefinition(compar, fn, false);
|
||
}
|
||
|
||
if (!is_find_predefinition)
|
||
{
|
||
continue;
|
||
}
|
||
else
|
||
{
|
||
predef_find = true;
|
||
foreach (common_parameter par in fn.parameters)
|
||
{
|
||
if (par.default_value != null)
|
||
{
|
||
syntax_tree_visitor.AddError(par.loc, "DEFAULT_VALUE_MUST_BE_ONLY_IN_FIRST_DECLARATION");
|
||
}
|
||
}
|
||
}
|
||
|
||
if (compar.function_code != null)
|
||
{
|
||
AddError(fn.loc, "FUNCTION_{0}_ALREADY_HAVE_A_BODY", fn.name);
|
||
}
|
||
|
||
if ((compar.polymorphic_state == PascalABCCompiler.SemanticTree.polymorphic_state.ps_static) !=
|
||
(fn.polymorphic_state == PascalABCCompiler.SemanticTree.polymorphic_state.ps_static))
|
||
{
|
||
syntax_tree_visitor.AddError(fn.loc, "CLASS_FUNCTION_ATTRIBUTE_MISMATCH");
|
||
}
|
||
|
||
common_method_node compiled_meth = fn as common_method_node;
|
||
|
||
if (compiled_meth != null)
|
||
{
|
||
common_method_node finded_method = (common_method_node)compar;
|
||
if (compiled_meth.is_constructor)
|
||
{
|
||
if (finded_method.is_constructor == false)
|
||
{
|
||
AddError(compiled_meth.loc, "CONSTRUCTOR_MUST_BE_REALIZED_WITH_CONSTRUCTOR_KEYWORD");
|
||
}
|
||
compiled_meth.return_value_type = finded_method.return_value_type;
|
||
convertion_data_and_alghoritms.create_function_return_variable(finded_method, null);
|
||
}
|
||
}
|
||
|
||
if (!convertion_data_and_alghoritms.eq_type_nodes(compar.return_value_type, fn.return_value_type) && fn.return_value_type != null && !(fn.return_value_type is undefined_type))
|
||
{
|
||
AddError(fn.loc, "FUNCTION_PREDEFINITION_AND_DEFINITION_HAVE_DIFFERENT_RESULT_TYPES");
|
||
}
|
||
|
||
//НУЖЕН СПИСОК ФУНКЦИЙ С ПРЕДОПРЕДЕЛЕНИЯМИ, ЧТОБЫ ОБНАРУЖИТЬ ОПИСАННЫЕ НО НЕ ОПРЕДЕЛЕННЫЕ
|
||
//Или не нужен???
|
||
|
||
//TODO: СИНХРОНИЗИРОВАТЬ АТТРИБУТЫ!!!!!
|
||
if (fn.is_overload)
|
||
{
|
||
compar.is_overload = true;
|
||
}
|
||
|
||
//TODO: Внимательно проверить следующий if.
|
||
if (compar.is_overload)
|
||
{
|
||
fn.is_overload = true;
|
||
last_created_function.symbol_kind = symbol_kind.sk_overload_function;
|
||
}
|
||
|
||
common_function_node cfn11 = _func_stack.pop();
|
||
compar.scope = cfn11.scope;
|
||
|
||
common_method_node cmnode = compar as common_method_node;
|
||
if (cmnode != null)
|
||
{
|
||
List<SymbolInfo> si_local = cfn11.scope.FindOnlyInScope(StringConstants.self_word);
|
||
if (si_local != null)
|
||
{
|
||
si_local.FirstOrDefault().sym_info = cmnode.self_variable;
|
||
}
|
||
}
|
||
|
||
//Удаляем текущую функцию
|
||
List<SymbolInfo> siint = null;
|
||
switch (converting_block())
|
||
{
|
||
case block_type.function_block:
|
||
{
|
||
_func_stack.top().functions_nodes_list.remove((common_in_function_function_node)fn);
|
||
siint = _func_stack.top().scope.FindOnlyInScope(fn.name);
|
||
break;
|
||
}
|
||
case block_type.namespace_block:
|
||
{
|
||
_cmn.functions.remove((common_namespace_function_node)fn);
|
||
siint = _cmn.scope.FindOnlyInScope(fn.name);
|
||
break;
|
||
}
|
||
case block_type.type_block:
|
||
{
|
||
//TODO: Доделать описание методов класса.
|
||
_ctn.methods.remove((common_method_node)fn);
|
||
siint = _ctn.scope.FindOnlyInScope(fn.name);
|
||
break;
|
||
}
|
||
case block_type.compiled_type_block:
|
||
{
|
||
if (syntax_tree_visitor.CompiledUnit.namespaces[0].functions.Contains((common_namespace_function_node)fn))
|
||
syntax_tree_visitor.CompiledUnit.namespaces[0].functions.remove((common_namespace_function_node)fn);
|
||
siint = _compiled_tn.find_in_type(fn.name);
|
||
break;
|
||
}
|
||
|
||
default:
|
||
{
|
||
throw new CompilerInternalError("Undefined block type");
|
||
}
|
||
}
|
||
bool compar_not_assign = true;
|
||
if (siint != null)
|
||
{
|
||
foreach (var siint_unit in siint)
|
||
{
|
||
if (siint_unit.sym_info == fn)
|
||
{
|
||
siint_unit.sym_info = compar;
|
||
compar_not_assign = false;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
if (compar_not_assign && siint != null)
|
||
siint.LastOrDefault().sym_info = compar;
|
||
|
||
|
||
//Мы удалили новую функцию. Сейчас мы должны перенести параметры из новой функции в старую.
|
||
//TODO: У новой функции может вообще не быть параметров. Они все в старой. Разобраться с этим. А зачем вообще переносить параметры?
|
||
|
||
if (compar.parameters.Count != 0)
|
||
{
|
||
if (fn.parameters.Count == 0)
|
||
{
|
||
foreach (common_parameter pr in compar.parameters)
|
||
{
|
||
compar.scope.AddSymbol(pr.name, new SymbolInfo(pr));
|
||
}
|
||
}
|
||
else
|
||
{
|
||
foreach (common_parameter pr in compar.parameters)
|
||
{
|
||
List<SymbolInfo> par_sim_info = fn.scope.FindOnlyInScope(pr.name);
|
||
par_sim_info.FirstOrDefault().sym_info = pr;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (fn.is_generic_function)
|
||
{
|
||
for (int i = 0; i < fn.generic_params.Count; ++i)
|
||
{
|
||
fn.generic_params[i] = compar.generic_params[i] as common_type_node;
|
||
common_type_node t_fn = fn.generic_params[i] as common_type_node;
|
||
common_type_node t_compar = compar.generic_params[i] as common_type_node;
|
||
/*t_fn.is_class = t_compar.is_class;
|
||
t_fn.internal_is_value = t_compar.internal_is_value;
|
||
t_fn.SetImplementingInterfaces(t_compar.ImplementingInterfaces);
|
||
(t_fn.Scope as SymbolTable.IInterfaceScope).TopInterfaceScopeArray =
|
||
(t_compar.Scope as SymbolTable.IInterfaceScope).TopInterfaceScopeArray;
|
||
t_fn.SetBaseType(t_compar.base_type);*/
|
||
if (t_compar.has_default_constructor)
|
||
{
|
||
generic_parameter_eliminations.add_default_ctor(t_fn);
|
||
}
|
||
List<SymbolInfo> par_sim_info = fn.scope.FindOnlyInScope(fn.generic_params[i].name);
|
||
par_sim_info.FirstOrDefault().sym_info = fn.generic_params[i] as common_type_node;
|
||
//t_fn.generic_function_container = compar;
|
||
}
|
||
//конверитируем параметры предописания в параметры описания.
|
||
List<type_node> fn_types = fn.get_generic_params_list();
|
||
foreach (common_parameter par in compar.parameters)
|
||
{
|
||
par.type = generic_convertions.determine_type(par.type, fn_types, true);
|
||
}
|
||
if (compar.return_value_type != null)
|
||
{
|
||
compar.return_value_type = generic_convertions.determine_type(compar.return_value_type, fn_types, true);
|
||
if (compar.return_variable != null)
|
||
{
|
||
compar.return_variable.type = compar.return_value_type;
|
||
}
|
||
}
|
||
foreach (generic_parameter_eliminations gpe in compar.parameters_eliminations)
|
||
{
|
||
|
||
}
|
||
compar.generic_params = fn.generic_params;
|
||
foreach (common_type_node tn in compar.generic_params)
|
||
{
|
||
tn.generic_function_container = compar;
|
||
}
|
||
}
|
||
|
||
_func_stack.push(compar);
|
||
compar.attributes.AddRange(fn.attributes);
|
||
//si_list.sym_info=fn;
|
||
break;
|
||
}
|
||
if (fn is common_method_node && !predef_find && syntax_tree_visitor.current_converted_method_not_in_class_defined && _explicit_interface_type == null)
|
||
{
|
||
AddError(new NoMethodInClassWithThisParams(fn as common_method_node, (fn as common_method_node).cont_type, fn.loc));
|
||
}
|
||
return !predef_find;
|
||
}
|
||
|
||
//Этот метод вызывается для предописания функции (только для предописания)
|
||
private void check_function_not_exists(common_function_node fn)
|
||
{
|
||
List<SymbolInfo> sil=null;
|
||
if (_func_stack.size<=1)
|
||
{
|
||
if (_ctn!=null)
|
||
{
|
||
sil=_ctn.Scope.FindOnlyInScope(fn.name);
|
||
}
|
||
else
|
||
{
|
||
sil=_cmn.scope.FindOnlyInScope(fn.name);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
common_function_node temp=_func_stack.pop();
|
||
sil=_func_stack.top().scope.FindOnlyInScope(fn.name);
|
||
_func_stack.push(temp);
|
||
}
|
||
if(sil != null)
|
||
foreach(SymbolInfo si in sil)
|
||
{
|
||
if (si.sym_info == fn || si.sym_info is basic_function_node)
|
||
continue;
|
||
#if (DEBUG)
|
||
if (si.sym_info.general_node_type!=general_node_type.function_node)
|
||
{
|
||
throw new CompilerInternalError("Function name is used to define not function.");
|
||
}
|
||
#endif
|
||
//compar - найденная функция
|
||
|
||
common_function_node compar=((common_function_node)(si.sym_info));
|
||
|
||
if (compar.is_overload==false)
|
||
{
|
||
AddError(new FunctionMustBeWithOverloadDirective(compar,fn));
|
||
}
|
||
if (convertion_data_and_alghoritms.function_eq_params(fn,compar,false))
|
||
{
|
||
if (fn.IsOperator && (fn.name == StringConstants.explicit_operator_name || fn.name == StringConstants.implicit_operator_name))
|
||
{
|
||
if (convertion_data_and_alghoritms.function_eq_params_and_result(fn,compar))
|
||
AddError(new FunctionDuplicateDefinition(compar, fn));
|
||
}
|
||
else
|
||
{
|
||
AddError(new FunctionDuplicateDefinition(compar,fn));
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
private void check_function_name(string name,location def_loc)
|
||
{
|
||
List<SymbolInfo> sil=find_only_in_namespace(name);
|
||
if (sil==null)
|
||
{
|
||
return;
|
||
}
|
||
|
||
if (sil.FirstOrDefault().sym_info.general_node_type!=general_node_type.function_node)
|
||
{
|
||
AddError(new FunctionNameIsUsedToDefineSomethigElse(def_loc,sil.FirstOrDefault().sym_info));
|
||
}
|
||
}
|
||
|
||
public common_property_node add_property(string property_name, location loc)
|
||
{
|
||
if (_ctn==null)
|
||
{
|
||
throw new CompilerInternalError("Property without class");
|
||
}
|
||
check_name_free(property_name,loc);
|
||
common_property_node pn = new common_property_node(property_name, _ctn, loc, _fal,
|
||
SemanticTree.polymorphic_state.ps_common);
|
||
_ctn.Scope.AddSymbol(property_name,new SymbolInfo(pn));
|
||
_ctn.properties.AddElement(pn);
|
||
return pn;
|
||
}
|
||
|
||
//(ssyy) модифицировал 05.07.2007
|
||
public void add_type(string name,type_node tn,location loc)
|
||
{
|
||
if(tn.is_class)
|
||
if (converting_block()!=block_type.namespace_block)
|
||
if (!(converting_block()==block_type.function_block))
|
||
{
|
||
AddError(new ClassCanNotBeDefinedInTypeOrFunction(name,loc));
|
||
}
|
||
compiled_type_node comp_tn = tn as compiled_type_node;
|
||
if (comp_tn != null)
|
||
{
|
||
if (_cmn.runtime_types.IndexOf(comp_tn) < 0)
|
||
{
|
||
_cmn.runtime_types.AddElement(comp_tn);
|
||
}
|
||
}
|
||
CurrentScope.AddSymbol(name, new SymbolInfo(tn));
|
||
if (tn is ref_type_node && converting_block() == block_type.namespace_block)
|
||
converted_namespace.ref_types.Add(tn as ref_type_node);
|
||
|
||
}
|
||
|
||
public statement_node code
|
||
{
|
||
get
|
||
{
|
||
switch (converting_block())
|
||
{
|
||
case block_type.function_block:
|
||
{
|
||
return _func_stack.top().function_code;
|
||
}
|
||
case block_type.type_block:
|
||
{
|
||
throw new CompilerInternalError("Type have no code.");
|
||
}
|
||
case block_type.namespace_block:
|
||
{
|
||
return _main_procedure;
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
set
|
||
{
|
||
switch (converting_block())
|
||
{
|
||
case block_type.function_block:
|
||
{
|
||
_func_stack.top().function_code=value;
|
||
break;
|
||
}
|
||
case block_type.type_block:
|
||
{
|
||
throw new CompilerInternalError("Type have no code.");
|
||
}
|
||
case block_type.namespace_block:
|
||
{
|
||
_main_procedure=value;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
public statement_node_stack cycle_stack
|
||
{
|
||
get
|
||
{
|
||
switch (converting_block())
|
||
{
|
||
case block_type.function_block:
|
||
{
|
||
return _func_stack.top().cycles_stack;
|
||
}
|
||
case block_type.type_block:
|
||
{
|
||
throw new CompilerInternalError("Can not get cycle from this point");
|
||
}
|
||
case block_type.namespace_block:
|
||
{
|
||
return _cycles_stack;
|
||
}
|
||
}
|
||
throw new CompilerInternalError("Undefined block type");
|
||
}
|
||
}
|
||
|
||
public void set_virtual(common_method_node cmn)
|
||
{
|
||
cmn.overrided_method = null;
|
||
cmn.newslot_awaited = true;
|
||
cmn.polymorphic_state = SemanticTree.polymorphic_state.ps_virtual;
|
||
}
|
||
|
||
//ssyy
|
||
public void set_virtual_abstract(common_method_node cmn)
|
||
{
|
||
cmn.overrided_method = null;
|
||
cmn.newslot_awaited = true;
|
||
cmn.polymorphic_state = SemanticTree.polymorphic_state.ps_virtual_abstract;
|
||
}
|
||
//\ssyy
|
||
|
||
public function_node FindMethodToOverride(common_namespace_function_node cmn)
|
||
{
|
||
type_node base_class = _compiled_tn;
|
||
if (base_class == null)
|
||
{
|
||
return null;
|
||
}
|
||
List<SymbolInfo> sil = base_class.find_in_type(cmn.name);
|
||
function_node fn = null;
|
||
if(sil != null)
|
||
foreach(SymbolInfo si in sil)
|
||
{
|
||
if (si.sym_info.general_node_type != general_node_type.function_node)
|
||
{
|
||
return null;
|
||
}
|
||
fn = si.sym_info as function_node;
|
||
//(ssyy) Сверяем как параметры функций, так и типы возвращаемых значений
|
||
if (cmn != fn && convertion_data_and_alghoritms.function_eq_params_and_result(cmn, fn))
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
if (sil == null)
|
||
{
|
||
return null;
|
||
}
|
||
compiled_function_node cfn_sec = fn as compiled_function_node;
|
||
|
||
if (cfn_sec != null)
|
||
{
|
||
if (cfn_sec.polymorphic_state != SemanticTree.polymorphic_state.ps_virtual && cfn_sec.polymorphic_state != SemanticTree.polymorphic_state.ps_virtual_abstract && !cfn_sec.IsFinal)
|
||
{
|
||
return null;
|
||
}
|
||
}
|
||
|
||
return fn;
|
||
}
|
||
|
||
public function_node FindMethodToOverride(common_method_node cmn)
|
||
{
|
||
type_node base_class = cmn.cont_type.base_type;
|
||
if (base_class == null)
|
||
{
|
||
return null;
|
||
}
|
||
List<SymbolInfo> sil = base_class.find_in_type(cmn.name, CurrentScope);
|
||
function_node fn = null;
|
||
SymbolInfo find_method = null;
|
||
if (sil != null)
|
||
{
|
||
foreach(SymbolInfo si in sil)
|
||
{
|
||
if (si.sym_info.general_node_type != general_node_type.function_node)
|
||
{
|
||
return null;
|
||
}
|
||
fn = si.sym_info as function_node;
|
||
//(ssyy) Сверяем как параметры функций, так и типы возвращаемых значений
|
||
if (convertion_data_and_alghoritms.function_eq_params_and_result(cmn, fn, true))
|
||
{
|
||
find_method = si;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
if (find_method == null)
|
||
{
|
||
return null;
|
||
}
|
||
common_method_node cmn_sec = fn as common_method_node;
|
||
if (cmn_sec != null)
|
||
{
|
||
if (cmn_sec.polymorphic_state != SemanticTree.polymorphic_state.ps_virtual && cmn_sec.polymorphic_state != SemanticTree.polymorphic_state.ps_virtual_abstract)
|
||
{
|
||
return null;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
compiled_function_node cfn_sec = fn as compiled_function_node;
|
||
if (cfn_sec != null)
|
||
{
|
||
if (cfn_sec.polymorphic_state != SemanticTree.polymorphic_state.ps_virtual && cfn_sec.polymorphic_state != SemanticTree.polymorphic_state.ps_virtual_abstract && !cfn_sec.IsFinal)
|
||
{
|
||
return null;
|
||
}
|
||
else if (cfn_sec.IsFinal)
|
||
return null;
|
||
}
|
||
else
|
||
{
|
||
throw new CompilerInternalError("Undefined method type.");
|
||
}
|
||
}
|
||
return fn;
|
||
}
|
||
|
||
public property_node FindPropertyToImplement(common_property_node cpn, string pure_name, type_node interf)
|
||
{
|
||
List<SymbolInfo> sil = interf.find_in_type(pure_name, CurrentScope);
|
||
property_node pn = null;
|
||
SymbolInfo find_property = null;
|
||
if (sil != null)
|
||
{
|
||
foreach (SymbolInfo si in sil)
|
||
{
|
||
if (si.sym_info.general_node_type != general_node_type.property_node)
|
||
{
|
||
return null;
|
||
}
|
||
pn = si.sym_info as property_node;
|
||
//(ssyy) Сверяем как параметры функций, так и типы возвращаемых значений
|
||
if (cpn.get_function == null && pn.get_function == null && pn.property_type == cpn.property_type)
|
||
{
|
||
find_property = si;
|
||
break;
|
||
}
|
||
else if (cpn.get_function != null && pn.get_function != null && convertion_data_and_alghoritms.function_eq_params_and_result(cpn.get_function, pn.get_function))
|
||
{
|
||
find_property = si;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
if (find_property == null)
|
||
{
|
||
return null;
|
||
}
|
||
return pn;
|
||
}
|
||
|
||
public property_node FindPropertyToOverride(common_property_node cpn)
|
||
{
|
||
type_node base_class = cpn.common_comprehensive_type.base_type;
|
||
if (base_class == null)
|
||
{
|
||
return null;
|
||
}
|
||
List<SymbolInfo> sil = base_class.find_in_type(cpn.name, CurrentScope);
|
||
property_node pn = null;
|
||
SymbolInfo find_property = null;
|
||
if (sil != null)
|
||
{
|
||
foreach (SymbolInfo si in sil)
|
||
{
|
||
if (si.sym_info.general_node_type != general_node_type.property_node)
|
||
{
|
||
return null;
|
||
}
|
||
pn = si.sym_info as property_node;
|
||
//(ssyy) Сверяем как параметры функций, так и типы возвращаемых значений
|
||
if (cpn.get_function == null && pn.get_function == null && pn.property_type == cpn.property_type)
|
||
{
|
||
find_property = si;
|
||
break;
|
||
}
|
||
else if (cpn.get_function != null && pn.get_function != null && convertion_data_and_alghoritms.function_eq_params_and_result(cpn.get_function, pn.get_function))
|
||
{
|
||
find_property = si;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
if (find_property == null)
|
||
{
|
||
return null;
|
||
}
|
||
common_property_node cpn_sec = pn as common_property_node;
|
||
if (cpn_sec != null)
|
||
{
|
||
if (cpn_sec.polymorphic_state != SemanticTree.polymorphic_state.ps_virtual && cpn_sec.polymorphic_state != SemanticTree.polymorphic_state.ps_virtual_abstract)
|
||
{
|
||
return null;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
compiled_property_node cmpn_sec = pn as compiled_property_node;
|
||
if (cmpn_sec != null)
|
||
{
|
||
if (cmpn_sec.polymorphic_state != SemanticTree.polymorphic_state.ps_virtual && cmpn_sec.polymorphic_state != SemanticTree.polymorphic_state.ps_virtual_abstract)
|
||
{
|
||
return null;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
throw new CompilerInternalError("Undefined property type.");
|
||
}
|
||
}
|
||
return pn;
|
||
}
|
||
|
||
public void set_override(common_property_node cpn)
|
||
{
|
||
cpn.polymorphic_state = SemanticTree.polymorphic_state.ps_virtual;
|
||
property_node overrided_property = FindPropertyToOverride(cpn);
|
||
if (overrided_property == null)
|
||
AddError(cpn.loc, "NO_PROPERTY_TO_OVERRIDE");
|
||
else
|
||
{
|
||
if (cpn.get_function is common_method_node)
|
||
{
|
||
(cpn.get_function as common_method_node).overrided_method = overrided_property.get_function;
|
||
(cpn.get_function as common_method_node).polymorphic_state = SemanticTree.polymorphic_state.ps_virtual;
|
||
}
|
||
if (cpn.set_function is common_method_node)
|
||
{
|
||
(cpn.set_function as common_method_node).overrided_method = overrided_property.set_function;
|
||
(cpn.set_function as common_method_node).polymorphic_state = SemanticTree.polymorphic_state.ps_virtual;
|
||
}
|
||
}
|
||
}
|
||
|
||
public void set_implement(common_property_node cpn, string pure_name, type_node interf)
|
||
{
|
||
property_node overrided_property = FindPropertyToImplement(cpn, pure_name, interf);
|
||
if (overrided_property == null)
|
||
AddError(cpn.loc, "NO_PROPERTY_TO_OVERRIDE");
|
||
else
|
||
{
|
||
if (cpn.get_function is common_method_node)
|
||
{
|
||
(cpn.get_function as common_method_node).overrided_method = overrided_property.get_function;
|
||
(cpn.get_function as common_method_node).is_final = true;
|
||
(cpn.get_function as common_method_node).newslot_awaited = true;
|
||
}
|
||
if (cpn.set_function is common_method_node)
|
||
{
|
||
(cpn.set_function as common_method_node).overrided_method = overrided_property.set_function;
|
||
(cpn.set_function as common_method_node).is_final = true;
|
||
(cpn.set_function as common_method_node).newslot_awaited = true;
|
||
}
|
||
}
|
||
}
|
||
|
||
public void set_override(common_method_node cmn)
|
||
{
|
||
cmn.polymorphic_state = SemanticTree.polymorphic_state.ps_virtual;
|
||
cmn.overrided_method = FindMethodToOverride(cmn);
|
||
if (cmn.overrided_method == null)
|
||
AddError(cmn.loc, "NO_METHOD_TO_OVERRIDE");
|
||
for (int i = 0; i < cmn.parameters.Count; i++)
|
||
{
|
||
var cp = cmn.parameters[i];
|
||
if (cp.type.IsDelegate && cp.type is common_type_node && (cp.type as common_type_node).name.IndexOf("$") != -1)
|
||
{
|
||
cp.type = cmn.overrided_method.parameters[i].type;
|
||
}
|
||
}
|
||
cmn.SetName(cmn.overrided_method.name);
|
||
}
|
||
|
||
//ssyy
|
||
//Добавляет блок в стек контекста, охватывающим блоком будет вершина стека
|
||
public void enter_code_block_with_bind()
|
||
{
|
||
if (_block_stack.Count > 0)
|
||
{
|
||
_block_stack.Push(new code_block(_block_stack.Peek()));
|
||
}
|
||
else
|
||
{
|
||
_block_stack.Push(new code_block(null));
|
||
}
|
||
}
|
||
|
||
//Добавляет блок в стек контекста, охватывающим блоком будет null
|
||
public void enter_code_block_without_bind()
|
||
{
|
||
_block_stack.Push(new code_block(null));
|
||
}
|
||
|
||
int finally_blocks_depth = 0;
|
||
bool disable_finally_control_break_check = false;
|
||
|
||
public void enter_finally_block()
|
||
{
|
||
finally_blocks_depth++;
|
||
disable_finally_control_break_check = false;
|
||
}
|
||
|
||
public void leave_finally_block()
|
||
{
|
||
finally_blocks_depth--;
|
||
}
|
||
|
||
public bool in_finally_block(bool ignore_disable_finally_control_break_check = false)
|
||
{
|
||
return (!disable_finally_control_break_check || ignore_disable_finally_control_break_check) && finally_blocks_depth > 0;
|
||
}
|
||
|
||
public void enter_in_cycle(statement_node stmt)
|
||
{
|
||
cycle_stack.push(stmt);
|
||
disable_finally_control_break_check = true;
|
||
}
|
||
|
||
public void leave_cycle()
|
||
{
|
||
cycle_stack.pop();
|
||
disable_finally_control_break_check = false;
|
||
}
|
||
|
||
//Убирает блок со стека
|
||
public void leave_code_block()
|
||
{
|
||
_block_stack.Pop();
|
||
}
|
||
|
||
//Проверяет, возможен ли переход от блока goto_block в label_block
|
||
public bool check_can_goto(code_block label_block, code_block goto_block)
|
||
{
|
||
code_block current_block = goto_block;
|
||
while (current_block != null)
|
||
{
|
||
if (current_block == label_block)
|
||
{
|
||
return true;
|
||
}
|
||
else
|
||
{
|
||
current_block = current_block.up_block;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
//\ssyy
|
||
|
||
|
||
|
||
internal string get_free_name(string template)
|
||
{
|
||
string name;
|
||
int i = 0;
|
||
while (CurrentScope.Find((name = string.Format(template, i++))) != null)
|
||
;
|
||
return name;
|
||
}
|
||
|
||
}
|
||
|
||
/// <summary>
|
||
/// Фасад над compilation_context, служащий для изменения контекста
|
||
/// </summary>
|
||
public class ContextChanger{
|
||
public compilation_context context;
|
||
|
||
private bool is_active;
|
||
|
||
public ContextChanger(compilation_context context)
|
||
{
|
||
this.context = context;
|
||
this.is_active = false;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Переход на глобальный уровень с сохранением контеста
|
||
/// </summary>
|
||
public void SaveContextAndUpToGlobalLevel()
|
||
{
|
||
this.is_active = true;
|
||
context.SaveContextAndUpToGlobalLevel();
|
||
}
|
||
|
||
/// <summary>
|
||
/// Переход на уровень класса с сохранением контеста
|
||
/// </summary>
|
||
public void SaveContextAndUpFromAllFunctionDefs()
|
||
{
|
||
this.is_active = true;
|
||
context.SaveContextAndUpFromAllFunctionDefs();
|
||
}
|
||
|
||
/// <summary>
|
||
/// Переход к ближайшему блоку определения с сохранением контеста
|
||
/// </summary>
|
||
public void SaveContextAndUpToNearestDefSect()
|
||
{
|
||
this.is_active = true;
|
||
context.SaveContextAndUpToNearestDefSect();
|
||
}
|
||
|
||
/// <summary>
|
||
/// Восстановление сохранённого контекста
|
||
/// </summary>
|
||
public void RestoreCurrentContext()
|
||
{
|
||
this.is_active = false;
|
||
context.RestoreCurrentContext();
|
||
}
|
||
|
||
public bool IsActive()
|
||
{
|
||
return is_active;
|
||
}
|
||
}
|
||
}
|