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_defs = new System.Collections.Generic.List(); private readonly System.Collections.Generic.Stack> var_defs_stack = new System.Collections.Generic.Stack>(); private readonly System.Collections.Generic.List _special_local_vars = new System.Collections.Generic.List(); private System.Collections.Generic.Stack _scope_stack = new System.Collections.Generic.Stack(); 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 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 type_stack = new System.Collections.Generic.Stack(); 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(); } 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