pascalabcnet/TreeConverter/TreeConversion/block_info.cs
Бондарев Иван e6e67c193c initial commit
2015-05-14 21:35:07 +02:00

1412 lines
44 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

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

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);
}
}
}