pascalabcnet/TreeConverter/TreeConversion/block_info.cs

1412 lines
44 KiB
C#
Raw Permalink Normal View History

2015-05-14 22:35:07 +03:00

using System;
using PascalABCCompiler.TreeRealization;
namespace PascalABCCompiler.TreeConverter
{
public enum block_type {function_block,type_block,namespace_block};
public class blocks
{
private common_namespace_node _cmn;
//TODO: Можно сделать возможность объявления вложенных типов.
private common_type_node _ctn;
private common_function_node_stack _func_stack=new common_function_node_stack();
private System.Collections.Generic.List<var_definition_node> var_defs =
new System.Collections.Generic.List<var_definition_node>();
private readonly System.Collections.Generic.Stack<System.Collections.Generic.List<var_definition_node>> var_defs_stack =
new System.Collections.Generic.Stack<System.Collections.Generic.List<var_definition_node>>();
private readonly System.Collections.Generic.List<local_variable> _special_local_vars =
new System.Collections.Generic.List<local_variable>();
private System.Collections.Generic.Stack<global::SymbolTable.Scope> _scope_stack
= new System.Collections.Generic.Stack<SymbolTable.Scope>();
private statement_node _main_procedure;
private SymbolInfo _last_created_function;
private statement_node_stack _cycles_stack=new statement_node_stack();
private int _num_of_for_cycles;
private convertion_data_and_alghoritms convertion_data_and_alghoritms;
private SemanticTree.field_access_level _fal;
public blocks(convertion_data_and_alghoritms convertion_data_and_alghoritms)
{
this.convertion_data_and_alghoritms = convertion_data_and_alghoritms;
}
public void reset()
{
_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;
rec_num = 1;
var_defs_stack.Clear();
type_stack.Clear();
clear_special_local_vars();
_scope_stack.Clear();
}
public void AddTemplate(string name, template_class tc, location loc)
{
check_name_free(name, loc);
_cmn.scope.AddSymbol(name, new SymbolInfo(tc));
}
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 System.Collections.Generic.List<local_variable> special_local_vars
{
get
{
return _special_local_vars;
}
}
*/
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");
break;
}
default:
{
throw new CompilerInternalError("Undefined block type");
}
}
}
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 common_function_node top_function
{
get
{
if (_func_stack.size==0)
{
return null;
}
return (_func_stack.top());
}
}
public common_type_node converted_type
{
get
{
return _ctn;
}
//ssyy
set
{
_ctn = value;
}
//\ssyy
}
//ssyy
public common_function_node_stack converted_func_stack
{
get
{
return _func_stack;
}
set
{
_func_stack = value;
}
}
//\ssyy
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);
}
_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 (_func_stack.size!=0)
{
return block_type.function_block;
}
if (_ctn!=null)
{
return block_type.type_block;
}
return block_type.namespace_block;
}
public common_type_node enter_in_type_method(string type_name, location loc)
{
SymbolInfo si = find(type_name);
if (si == null)
{
throw new UndefinedNameReference(type_name, loc);
}
if (si.sym_info.general_node_type != general_node_type.type_node)
{
throw new TypeNameExpected(type_name,si.sym_info,loc);
}
#if DEBUG
if (si.Next != null)
{
throw new CompilerInternalError("Must find only type, found some other.");
}
#endif
if (si.sym_info.semantic_node_type != semantic_node_type.common_type_node)
{
throw new OnlyCommonTypeMethodDefinitionAllowed(((type_node)si.sym_info), loc);
}
//TODO: В случае создания вложенных классов этот код надо поправить.
common_type_node ctn = si.sym_info as common_type_node;
_ctn = ctn;
return ctn;
}
public void leave_type_method()
{
_ctn = null;
}
private readonly System.Collections.Generic.Stack<common_type_node> type_stack = new System.Collections.Generic.Stack<common_type_node>();
public void leave_record()
{
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(compiler_string_consts.result_variable_name, si);
return si;
}
public common_function_node create_function(string name,location def_loc)
{
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);
common_in_function_function_node ciffn;
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);
top_func.scope.AddSymbol(name,_last_created_function);
cfn=ciffn;
break;
}
case block_type.type_block:
{
common_method_node cmmn;
SymbolTable.Scope scope = convertion_data_and_alghoritms.symbol_table.CreateClassMethodScope(_cmn.scope, _ctn.Scope);
//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);
_ctn.Scope.AddSymbol(name,_last_created_function);
_ctn.methods.AddElement(cmmn);
local_variable lv = new local_variable(compiler_string_consts.self_word, _ctn, cmmn, def_loc);
cmmn.scope.AddSymbol(compiler_string_consts.self_word, new SymbolInfo(lv));
cmmn.self_variable = lv;
cmmn.var_definition_nodes_list.AddElement(lv);
cfn=cmmn;
break;
}
case block_type.namespace_block:
{
common_namespace_function_node cnfnn;
SymbolTable.Scope scope = convertion_data_and_alghoritms.symbol_table.CreateScope(_cmn.scope);
cnfnn=new common_namespace_function_node(name,def_loc,_cmn,scope);
_cmn.functions.AddElement(cnfnn);
_last_created_function=new SymbolInfo(cnfnn);
_cmn.scope.AddSymbol(name,_last_created_function);
cfn=cnfnn;
break;
}
}
_func_stack.push(cfn);
return cfn;
}
public common_type_node create_type(string name,location def_loc)
{
check_name_free(name,def_loc);
if (converting_block()!=block_type.namespace_block)
{
throw new TypeCanNotBeDefinedInTypeOrFunction(name,def_loc);
}
SymbolTable.ClassScope scope = convertion_data_and_alghoritms.symbol_table.CreateClassScope(_cmn.scope,null);
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));
//_cmn.types.AddElement(tctn);
_ctn=tctn;
SystemLibrary.SystemLibrary.init_reference_type(tctn);
return tctn;
}
/****************************modified***********************/
private int rec_num=0;
public common_type_node create_record_type(location def_loc)
{
SymbolTable.ClassScope scope = convertion_data_and_alghoritms.symbol_table.CreateClassScope(_cmn.scope, null);
string name = "$record$" + rec_num++;
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.SetBaseType(compiled_type_node.get_type_node(typeof(ValueType)));
//_cmn.types.AddElement(tctn);
if (_ctn != null) type_stack.Push(_ctn);
_ctn = tctn;
SystemLibrary.SystemLibrary.init_reference_type(tctn);
return tctn;
}
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;
}
}
/*************************************************************/
public var_definition_node add_var_definition(string name,location loc)
{
check_name_free(name,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,top_func,loc);
vdn=lv;
top_func.var_definition_nodes_list.AddElement(lv);
top_func.scope.AddSymbol(name,new SymbolInfo(lv));
var_defs.Add(vdn);
break;
}
case block_type.type_block:
{
//TODO:сделать static и virtual.
class_field cf = new class_field(name, _ctn, SemanticTree.polymorphic_state.ps_common,_fal,loc);
vdn=cf;
_ctn.Scope.AddSymbol(name,new SymbolInfo(cf));
_ctn.fields.AddElement(cf);
var_defs.Add(vdn);
break;
}
case block_type.namespace_block:
{
namespace_variable nsv=new namespace_variable(name,_cmn,loc);
vdn=nsv;
_cmn.scope.AddSymbol(name,new SymbolInfo(nsv));
_cmn.variables.AddElement(nsv);
var_defs.Add(vdn);
break;
}
}
return vdn;
}
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");
}
}
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 (compiler_string_consts.delegate_type_name_template+get_and_postinc_num_of_for_cycles());
}
public var_definition_node create_for_temp_variable(type_node type,location loc)
{
num_of_for_cycles=num_of_for_cycles+1;
string name=compiler_string_consts.temp_for_variable_name+num_of_for_cycles.ToString();
return create_temp_variable(name,type,loc);
}
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;
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);
_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 void make_constructor()
{
#if (DEBUG)
if (converting_block()!=block_type.function_block)
{
throw new CompilerInternalError("Create constructor call without function");
}
if (_func_stack.top().node_location_kind!=SemanticTree.node_location_kind.in_class_location)
{
throw new CompilerInternalError("Create constructor applied to non class method");
}
#endif
common_function_node top_func=_func_stack.top();
top_func.return_value_type=_ctn;
common_method_node top_method=(common_method_node)top_func;
common_method_node cmn=new common_method_node(top_func.name,_ctn,top_method.loc,_ctn,
SemanticTree.polymorphic_state.ps_static,_fal,top_func.scope);
cmn.is_constructor=true;
cmn.is_overload=top_function.is_overload;
//parameter_list pl = new parameter_list();
foreach (common_parameter pr in top_method.parameters)
{
common_parameter new_par = new common_parameter(pr.name, pr.type, pr.parameter_type, cmn, pr.concrete_parameter_type,
pr.default_value, pr.loc);
cmn.parameters.AddElement(new_par);
}
//cmn.parameters.AddRange(top_method.parameters);
statements_list stl=new statements_list(top_func.loc);
cmn.function_code=stl;
this_node thn=new this_node(_ctn,top_func.loc);
common_method_call csmc=new common_method_call(top_method,thn,top_func.loc);
foreach(common_parameter cp in cmn.parameters)
{
common_parameter_reference cpr=new common_parameter_reference(cp,0,top_func.loc);
csmc.parametres.AddElement(cpr);
}
stl.statements.AddElement(csmc);
_ctn.methods.AddElement(cmn);
top_method.pascal_associated_constructor=cmn;
}
public void close_var_definition_list(type_node tp)
{
if (var_defs.Count==0)
{
return;
}
foreach(var_definition_node vdn in var_defs)
{
vdn.type=tp;
}
var_defs.Clear();
}
public SymbolInfo find(string name)
{
switch (converting_block())
{
case block_type.function_block:
{
return _func_stack.top().find(name);
}
case block_type.type_block:
{
return _ctn.find(name);
}
case block_type.namespace_block:
{
return _cmn.find(name);
}
}
return null;
}
public SymbolInfo find_only_in_namespace(string name)
{
switch (converting_block())
{
case block_type.function_block:
{
return _func_stack.top().find_only_in_namespace(name);
}
case block_type.type_block:
{
return _ctn.Scope.FindOnlyInScope(name);
}
case block_type.namespace_block:
{
return _cmn.scope.FindOnlyInScope(name);
}
}
return null;
}
public void leave_interface_part()
{
_cmn = null;
}
public void check_all_name_unit_defined(common_unit_node cmn)
{
common_namespace_node cfn = cmn.namespaces[0];
foreach (common_namespace_function_node cnfn in cfn.functions)
{
if (cnfn.function_code == null)
{
throw new FunctionPredefinitionWithoutDefinition(cnfn);
}
}
}
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;
}
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:
{
//TODO: Может и сюда вставить check_predefinition_defined, несмотря на то, что в данный момент он ничего не делает.
_cmn.types.AddElement(_ctn);
_ctn=null;
break;
}
case block_type.namespace_block:
{
check_predefinition_defined();
_cmn=null;
break;
}
}
}
public SymbolInfo last_created_function
{
get
{
return _last_created_function;
}
}
public void close_function_params(bool body_exists)
{
if (body_exists)
{
close_function_params_with_body();
}
else
{
close_function_params_without_body();
}
}
private void close_function_params_without_body()
{
check_function_not_exists(_func_stack.top());
}
private void close_function_params_with_body()
{
check_unique_or_predefined(_func_stack.top());
}
public void check_name_free(string name,SemanticTree.ILocation name_loc)
{
SymbolInfo si=find_only_in_namespace(name);
if (si==null)
{
return;
}
SemanticTree.ILocation first_loc=convertion_data_and_alghoritms.get_location(si.sym_info);
//TODO: Можно передавать список всех повторных объявлений.
throw new NameRedefinition(first_loc,name_loc);
}
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)
{
throw new DifferentParameterNameInFunctionPredefinitionAndDefinition(
(common_parameter)predef.parameters[param_num],
(common_parameter)def.parameters[param_num],
predef,def);
}
}
return true;
}
if (error_on_false)
{
throw new FunctionDefinitionHaveDifferentParamsWithPredifinition(predef,def);
}
return false;
}
private 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)
{
throw new FunctionPredefinitionWithoutDefinition(cfn);
}
}
break;
}
case block_type.namespace_block:
{
foreach(common_function_node cfn in _cmn.functions)
{
if (cfn.function_code==null)
{
throw new FunctionPredefinitionWithoutDefinition(cfn);
}
}
foreach (common_type_node ctn in _cmn.types)
{
foreach (common_method_node cmn in ctn.methods)
{
if (cmn.function_code == null)
{
throw new FunctionPredefinitionWithoutDefinition(cmn);
}
}
}
break;
}
case block_type.type_block:
{
//TODO: Доделать. На завершение компиляции модуля нужно просматривать все методы типов и функции в чатсях interface и implementation на предмет того, что все объявленные функции определены.
break;
}
default:
{
throw new CompilerInternalError("Undefined block type");
}
}
}
//Я хочу модифицировать этот метод так, чтобы в случае предописания наличия метода
//он не выкидывал исключение, а понимал все правильно
//Этот метод вызывается только для функций с телом
private void check_unique_or_predefined(common_function_node fn)
{
SymbolInfo si=null;
if (_func_stack.size<=1)
{
if (_ctn!=null)
{
//TODO: Спрость у Саши насчет того, что возвращает этот метод. Он долхен возвращать список найденных методов, а не единственный экземпляр.
si=_ctn.Scope.FindOnlyInScope(fn.name);
}
else
{
si=_cmn.scope.FindOnlyInScope(fn.name);
}
}
else
{
common_function_node temp=_func_stack.pop();
si = _func_stack.top().scope.FindOnlyInScope(fn.name);
_func_stack.push(temp);
}
//SymbolInfo si=find_only_in_namespace(fn.name);
//И эта проверка наверно не нужна, но пусть пока повисит
//Тем более с ней, наверное, быстрее работает
//if (si.Next==null)
//{
// return;
//}
//Тут я добавляю проверку: если это предописание, то все хорошо
/*if (si.Next.Next==null)
{
if (fnd.function_code==null)
{
}
}*/
//Как я понимаю все должно работать правильно без следующего фрагмента
/*if (fn.is_overload==false)
{
//fnd - найденная функция
common_function_node fnd=null;
if (si.sym_info==fn)
{
fnd=(common_function_node)si.Next.sym_info;
}
else
{
fnd=(common_function_node)si.sym_info;
}
throw new FunctionMustBeWithOverloadDirective(fnd,fn);
}*/
while(si!=null)
{
if (si.sym_info==fn)
{
si=si.Next;
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.function_code!=null)
{
if (compar.is_overload==false)
{
throw new FunctionMustBeWithOverloadDirective(compar,fn);
}
if (convertion_data_and_alghoritms.function_eq_params(fn,compar))
{
throw new FunctionDuplicateDefinition(compar,fn);
}
si=si.Next;
continue;
}
bool is_find_predefinition=false;
if (compar.is_overload==false)
{
//Если нет параметров в описании тела функции
if (fn.parameters.Count==0)
{
is_find_predefinition=true;
//Добавляем все описанные параметры
/*
foreach(parameter par in compar.parameters)
{
//Тут, конечно, приведение типа параметра, но оно вроде всегда должно быть такого типа.
common_parameter intcpar=(common_parameter)par;
common_parameter new_par = new common_parameter(intcpar.name, intcpar.type, intcpar.parameter_type,
fn, intcpar.concrete_parameter_type, intcpar.default_value, intcpar.loc);
fn.parameters.AddElement(new_par);
fn.scope.AddSymbol(new_par.name,new SymbolInfo(new_par));
}
compar.scope=fn.scope;
*/
}
else
{
is_find_predefinition=is_predefinition(compar,fn,true);
}
}
else
{
is_find_predefinition=is_predefinition(compar,fn,false);
}
if (!is_find_predefinition)
{
si = si.Next;
continue;
}
if (compar.function_code!=null)
{
throw new FunctionAlreadyHaveABody(compar, fn);
}
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.pascal_associated_constructor == null)
{
throw new ConstructorMustBeRealizedWithConstructorKeyword(finded_method,compiled_meth,compiled_meth.loc);
}
compiled_meth.return_value_type = finded_method.return_value_type;
convertion_data_and_alghoritms.create_function_return_variable(finded_method,null);
}
}
if (compar.return_value_type!=fn.return_value_type)
{
throw new FunctionPredefinitionAndDefinitionHaveDifferentResultType(compar,fn);
}
//НУЖЕН СПИСОК ФУНКЦИЙ С ПРЕДОПРЕДЕЛЕНИЯМИ, ЧТОБЫ ОБНАРУЖИТЬ ОПИСАННЫЕ НО НЕ ОПРЕДЕЛЕННЫЕ
//Или не нужен???
//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)
{
SymbolInfo si_local = cfn11.scope.FindOnlyInScope(compiler_string_consts.self_word);
if (si_local != null)
{
si_local.sym_info = cmnode.self_variable;
}
}
//Удаляем текущую функцию
SymbolInfo siint = null;
//TODO: Возможно в коде ниже следует вызывать не Find а FindOnlyInNamespace.
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;
}
default:
{
throw new CompilerInternalError("Undefined block type");
}
}
while (siint.sym_info != fn)
{
siint = siint.Next;
}
siint.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)
{
SymbolInfo par_sim_info=fn.scope.FindOnlyInScope(pr.name);
par_sim_info.sym_info = pr;
}
}
}
/*
compar.parameters.clear();
foreach (common_parameter pr in fn.parameters)
{
pr.common_function = compar;
compar.parameters.AddElement(pr);
}
*/
_func_stack.push(compar);
//si.sym_info=fn;
break;
}
}
//Этот метод вызывается для предописания функции (только для предописания)
private void check_function_not_exists(common_function_node fn)
{
SymbolInfo si=null;
if (_func_stack.size<=1)
{
if (_ctn!=null)
{
si=_ctn.Scope.FindOnlyInScope(fn.name);
}
else
{
si=_cmn.scope.FindOnlyInScope(fn.name);
}
}
else
{
common_function_node temp=_func_stack.pop();
si=_func_stack.top().scope.FindOnlyInScope(fn.name);
_func_stack.push(temp);
}
//SymbolInfo si=find_only_in_namespace(fn.name);
//И эта проверка наверно не нужна, но пусть пока повисит
//Тем более с ней, наверное, быстрее работает
//Лучше удалю пока
//if (si.Next==null)
//{
// return;
//}
while(si!=null)
{
if (si.sym_info==fn)
{
si=si.Next;
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)
{
throw new FunctionMustBeWithOverloadDirective(compar,fn);
}
if (convertion_data_and_alghoritms.function_eq_params(fn,compar))
{
throw new FunctionDuplicateDefinition(compar,fn);
}
si=si.Next;
}
}
private void check_function_name(string name,location def_loc)
{
SymbolInfo si=find_only_in_namespace(name);
if (si==null)
{
return;
}
if (si.sym_info.general_node_type!=general_node_type.function_node)
{
throw new FunctionNameIsUsedToDefineSomethigElse(def_loc,si.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;
}
public void add_type(string name,type_node tn,location loc)
{
if (converting_block()!=block_type.namespace_block)
if (!(converting_block()==block_type.function_block && !tn.is_class))
{
throw new TypeCanNotBeDefinedInTypeOrFunction(name,loc);
}
//TODO: Почему не было следующего оператора.
//_cmn.types.AddElement(tn);
if (tn is compiled_type_node)
_cmn.runtime_types.AddElement(tn as compiled_type_node);
_cmn.scope.AddSymbol(name,new SymbolInfo(tn));
}
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.polymorphic_state = SemanticTree.polymorphic_state.ps_virtual;
}
public void set_override(common_method_node cmn)
{
cmn.polymorphic_state = SemanticTree.polymorphic_state.ps_virtual;
type_node base_class = cmn.cont_type.base_type;
if (base_class == null)
{
throw new NoMethodToOverride(cmn);
}
SymbolInfo si = base_class.find_in_type(cmn.name);
function_node fn = null;
while (si != null)
{
if (si.sym_info.general_node_type != general_node_type.function_node)
{
throw new NoMethodToOverride(cmn);
}
fn = si.sym_info as function_node;
if (convertion_data_and_alghoritms.function_eq_params(cmn, fn))
{
break;
}
si = si.Next;
}
if (si == null)
{
throw new NoMethodToOverride(cmn);
}
common_method_node cmn_sec = fn as common_method_node;
if (cmn_sec != null)
{
if (cmn_sec.polymorphic_state != SemanticTree.polymorphic_state.ps_virtual)
{
throw new NoMethodToOverride(cmn);
}
}
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)
{
throw new NoMethodToOverride(cmn);
}
}
else
{
throw new CompilerInternalError("Undefined method type.");
}
}
cmn.overrided_method = fn;
cmn.SetName(fn.name);
}
}
}