stage3/fill_candidate_datatypes.cc
changeset 438 744b125d911e
parent 437 0e09a8840c92
child 439 cf7d6862033d
equal deleted inserted replaced
437:0e09a8840c92 438:744b125d911e
    89 
    89 
    90 		/* Get the parameter type */
    90 		/* Get the parameter type */
    91 		param_type = base_type(fp_iterator.param_type());
    91 		param_type = base_type(fp_iterator.param_type());
    92 		
    92 		
    93 		/* check whether one of the candidate_data_types of the value being passed is the same as the param_type */
    93 		/* check whether one of the candidate_data_types of the value being passed is the same as the param_type */
       
    94 			/* TODO
       
    95 			 * call  int search_in_datatype_list(symbol_c *datatype, std::vector <symbol_c *> candidate_datatypes);
       
    96 			 * instead of using for loop!
       
    97 			 */
    94 		for(i = 0; i < call_param_value->candidate_datatypes.size(); i++) {
    98 		for(i = 0; i < call_param_value->candidate_datatypes.size(); i++) {
    95 			/* If found (correct data type being passed), then stop the search */
    99 			/* If found (correct data type being passed), then stop the search */
    96 			if(is_type_equal(param_type, call_param_value->candidate_datatypes[i])) break;
   100 			if(is_type_equal(param_type, call_param_value->candidate_datatypes[i])) break;
    97 		}
   101 		}
    98 		/* if we reached the end of the loop, and no compatible type found, then return false */
   102 		/* if we reached the end of the loop, and no compatible type found, then return false */
   136 		param_name = fp_iterator.search(call_param_name);
   140 		param_name = fp_iterator.search(call_param_name);
   137 		if(param_name == NULL) return false;
   141 		if(param_name == NULL) return false;
   138 		/* Get the parameter type */
   142 		/* Get the parameter type */
   139 		param_type = base_type(fp_iterator.param_type());
   143 		param_type = base_type(fp_iterator.param_type());
   140 		/* check whether one of the candidate_data_types of the value being passed is the same as the param_type */
   144 		/* check whether one of the candidate_data_types of the value being passed is the same as the param_type */
       
   145 			/* TODO
       
   146 			 * call  int search_in_datatype_list(symbol_c *datatype, std::vector <symbol_c *> candidate_datatypes);
       
   147 			 * instead of using for loop!
       
   148 			 */
   141 		for (i = 0; i < call_param_types.size(); i++) {
   149 		for (i = 0; i < call_param_types.size(); i++) {
   142 			/* If found (correct data type being passed), then stop the search */
   150 			/* If found (correct data type being passed), then stop the search */
   143 			if(is_type_equal(param_type, call_param_types[i])) break;
   151 			if(is_type_equal(param_type, call_param_types[i])) break;
   144 		}
   152 		}
   145 		/* if we reached the end of the loop, and no compatible type found, then return false */
   153 		/* if we reached the end of the loop, and no compatible type found, then return false */
   147 
   155 
   148 	}
   156 	}
   149 	/* call is compatible! */
   157 	/* call is compatible! */
   150 	return true;
   158 	return true;
   151 }
   159 }
       
   160 
       
   161 
       
   162 
       
   163 
       
   164 /* Handle a generic function call!
       
   165  * Assumes that the parameter_list containing the values being passed in this function invocation
       
   166  * has already had all the candidate_datatype lists filled in!
       
   167  *
       
   168  * All parameters being passed to the called function MUST be in the parameter list to which f_call points to!
       
   169  * This means that, for non formal function calls in IL, de current (default value) must be artificially added to the
       
   170  * beginning of the parameter list BEFORE calling handle_function_call().
       
   171  */
       
   172 /*
       
   173 typedef struct {
       
   174   symbol_c *function_name,
       
   175   symbol_c *nonformal_operand_list,
       
   176   symbol_c *   formal_operand_list,
       
   177 
       
   178   std::vector <symbol_c *> &candidate_functions,  
       
   179   symbol_c &*called_function_declaration,
       
   180   int      &extensible_param_count
       
   181 } generic_function_call_t;
       
   182 */
       
   183 /*
       
   184 void narrow_candidate_datatypes_c::narrow_function_invocation(symbol_c *fcall, generic_function_call_t fcall_data) {
       
   185 void *fill_candidate_datatypes_c::handle_function_call(symbol_c *f_call, symbol_c *function_name, invocation_type_t invocation_type,
       
   186                                                        std::vector <symbol_c *> *candidate_datatypes,
       
   187                                                        std::vector <symbol_c *> *candidate_functions) {
       
   188   */
       
   189 void fill_candidate_datatypes_c::handle_function_call(symbol_c *fcall, generic_function_call_t fcall_data) {
       
   190 	function_declaration_c *f_decl;
       
   191 	list_c *parameter_list;
       
   192 	list_c *parameter_candidate_datatypes;
       
   193 	symbol_c *returned_parameter_type;
       
   194 
       
   195 	if (debug) std::cout << "function()\n";
       
   196 
       
   197 	function_symtable_t::iterator lower = function_symtable.lower_bound(fcall_data.function_name);
       
   198 	function_symtable_t::iterator upper = function_symtable.upper_bound(fcall_data.function_name);
       
   199 	/* If the name of the function being called is not found in the function symbol table, then this is an invalid call */
       
   200 	/* Since the lexical parser already checks for this, then if this occurs then we have an internal compiler error. */
       
   201 	if (lower == function_symtable.end()) ERROR;
       
   202 	
       
   203 	/* Look for all compatible function declarations, and add their return datatypes 
       
   204 	 * to the candidate_datatype list of this function invocation. 
       
   205 	 *
       
   206 	 * If only one function exists, we add its return datatype to the candidate_datatype list,
       
   207 	 * even if the parameters passed to it are invalid.
       
   208 	 * This guarantees that the remainder of the expression in which the function call is inserted
       
   209 	 * is treated as if the function call returns correctly, and therefore does not generate
       
   210 	 * spurious error messages.
       
   211 	 * Even if the parameters to the function call are invalid, doing this is still safe, as the 
       
   212 	 * expressions inside the function call will themselves have erros and will  guarantee that 
       
   213 	 * compilation is aborted in stage3 (in print_datatypes_error_c).
       
   214 	 */
       
   215 	if (function_symtable.multiplicity(fcall_data.function_name) == 1) {
       
   216 		f_decl = function_symtable.get_value(lower);
       
   217 		returned_parameter_type = base_type(f_decl->type_name);
       
   218 		fcall_data.candidate_functions.push_back(f_decl);
       
   219 		fcall->    candidate_datatypes.push_back(returned_parameter_type);
       
   220 	}
       
   221 	for(; lower != upper; lower++) {
       
   222 		bool compatible = false;
       
   223 		
       
   224 		f_decl = function_symtable.get_value(lower);
       
   225 		/* Check if function declaration in symbol_table is compatible with parameters */
       
   226 		if (NULL != fcall_data.nonformal_operand_list) compatible=match_nonformal_call(fcall, f_decl);
       
   227 		if (NULL != fcall_data.   formal_operand_list) compatible=   match_formal_call(fcall, f_decl);
       
   228 		if (compatible) {
       
   229 			/* Add the data type returned by the called functions. 
       
   230 			 * However, only do this if this data type is not already present in the candidate_datatypes list_c
       
   231 			 */
       
   232 			/* TODO
       
   233 			 * call  int search_in_datatype_list(symbol_c *datatype, std::vector <symbol_c *> candidate_datatypes);
       
   234 			 * instead of using for loop!
       
   235 			 */
       
   236 			unsigned int k;
       
   237 			returned_parameter_type = base_type(f_decl->type_name);
       
   238 			for(k = 0; k < fcall->candidate_datatypes.size(); k++) {
       
   239 				if (is_type_equal(returned_parameter_type, fcall->candidate_datatypes[k]))
       
   240 					break;
       
   241 			}
       
   242 			if (k >= fcall->candidate_datatypes.size()) {
       
   243 				fcall->    candidate_datatypes.push_back(returned_parameter_type);
       
   244 				fcall_data.candidate_functions.push_back(f_decl);
       
   245 			}
       
   246 		}
       
   247 	}
       
   248 	if (debug) std::cout << "end_function() [" << fcall->candidate_datatypes.size() << "] result.\n";
       
   249 	return;
       
   250 }
       
   251 
   152 
   252 
   153 
   253 
   154 
   254 
   155 
   255 
   156 /* a helper function... */
   256 /* a helper function... */
   665 	symbol->il_simple_operator->accept(*this);
   765 	symbol->il_simple_operator->accept(*this);
   666 	il_operand = NULL;
   766 	il_operand = NULL;
   667 	return NULL;
   767 	return NULL;
   668 }
   768 }
   669 
   769 
       
   770 
       
   771 /* | function_name [il_operand_list] */
       
   772 /* NOTE: The parameters 'called_function_declaration' and 'extensible_param_count' are used to pass data between the stage 3 and stage 4. */
       
   773 // SYM_REF2(il_function_call_c, function_name, il_operand_list, symbol_c *called_function_declaration; int extensible_param_count;)
   670 void *fill_candidate_datatypes_c::visit(il_function_call_c *symbol) {
   774 void *fill_candidate_datatypes_c::visit(il_function_call_c *symbol) {
   671 }
   775 	/* The first parameter of a non formal function call in IL will be the 'current value' (i.e. the prev_il_instruction)
   672 
   776 	 * In order to be able to handle this without coding special cases, we will simply prepend that symbol
   673 /* MJS: Manuele, could you please not delete the following 2 lines of comments. They help me understand where this class is used
   777 	 * to the il_operand_list, and remove it later (in the print_datatypes_error_c).
   674  *     and when it is created by bison - syntax parse, and how it can show up in the abstract syntax tree.
   778 	 *
   675  *
   779 	 * However, if no further paramters are given, then il_operand_list will be NULL, and we will
   676  *       Actually, it could be helpful if we could have all the similar comments already present in visit_expression_type_c
   780 	 * need to create a new object to hold the pointer to prev_il_instruction.
   677  *       in the 3 new classes fill/narrow/print candidate datatype 
   781 	 * This change will also be undone later in print_datatypes_error_c.
   678  */
   782 	 */
       
   783 	if (NULL == symbol->il_operand_list)  symbol->il_operand_list = new il_operand_list_c;
       
   784 	if (NULL == symbol->il_operand_list)  ERROR;
       
   785 
       
   786 	symbol->il_operand_list->accept(*this);
       
   787 
       
   788 	if (NULL == prev_il_instruction)      return NULL;
       
   789 	((list_c *)symbol->il_operand_list)->insert_element(prev_il_instruction, 0);	
       
   790 
       
   791 	generic_function_call_t fcall_param = {
       
   792 	/* fcall_param.function_name               = */ symbol->function_name,
       
   793 	/* fcall_param.nonformal_operand_list      = */ symbol->il_operand_list,
       
   794 	/* fcall_param.formal_operand_list         = */ NULL,
       
   795 	/* fcall_param.candidate_functions         = */ symbol->candidate_functions,
       
   796 	/* fcall_param.called_function_declaration = */ symbol->called_function_declaration,
       
   797 	/* fcall_param.extensible_param_count      = */ symbol->extensible_param_count
       
   798 	};
       
   799 	handle_function_call(symbol, fcall_param);
       
   800 
       
   801 	if (debug) std::cout << "il_function_call_c [" << symbol->candidate_datatypes.size() << "] result.\n";
       
   802 	return NULL;
       
   803 }
       
   804 
       
   805 
   679 /* | il_expr_operator '(' [il_operand] eol_list [simple_instr_list] ')' */
   806 /* | il_expr_operator '(' [il_operand] eol_list [simple_instr_list] ')' */
   680 // SYM_REF3(il_expression_c, il_expr_operator, il_operand, simple_instr_list);
   807 // SYM_REF3(il_expression_c, il_expr_operator, il_operand, simple_instr_list);
   681 void *fill_candidate_datatypes_c::visit(il_expression_c *symbol) {
   808 void *fill_candidate_datatypes_c::visit(il_expression_c *symbol) {
   682   if (NULL != symbol->il_operand)
   809   if (NULL != symbol->il_operand)
   683     symbol->il_operand->accept(*this);
   810     symbol->il_operand->accept(*this);
   715 }
   842 }
   716 
   843 
   717 void *fill_candidate_datatypes_c::visit(il_fb_call_c *symbol) {
   844 void *fill_candidate_datatypes_c::visit(il_fb_call_c *symbol) {
   718 }
   845 }
   719 
   846 
       
   847 /* | function_name '(' eol_list [il_param_list] ')' */
       
   848 /* NOTE: The parameter 'called_function_declaration' is used to pass data between the stage 3 and stage 4. */
       
   849 // SYM_REF2(il_formal_funct_call_c, function_name, il_param_list, symbol_c *called_function_declaration; int extensible_param_count;)
   720 void *fill_candidate_datatypes_c::visit(il_formal_funct_call_c *symbol) {
   850 void *fill_candidate_datatypes_c::visit(il_formal_funct_call_c *symbol) {
   721 
   851 	symbol->il_param_list->accept(*this);
       
   852 
       
   853 	generic_function_call_t fcall_param = {
       
   854 	/* fcall_param.function_name               = */ symbol->function_name,
       
   855 	/* fcall_param.nonformal_operand_list      = */ NULL,
       
   856 	/* fcall_param.formal_operand_list         = */ symbol->il_param_list,
       
   857 	/* fcall_param.candidate_functions         = */ symbol->candidate_functions,
       
   858 	/* fcall_param.called_function_declaration = */ symbol->called_function_declaration,
       
   859 	/* fcall_param.extensible_param_count      = */ symbol->extensible_param_count
       
   860 	};
       
   861 	handle_function_call(symbol, fcall_param);
       
   862 
       
   863 	if (debug) std::cout << "il_formal_funct_call_c [" << symbol->candidate_datatypes.size() << "] result.\n";
       
   864 	return NULL;
   722 }
   865 }
   723 
   866 
   724 /*
   867 /*
   725     void *visit(il_operand_list_c *symbol);
   868     void *visit(il_operand_list_c *symbol);
   726     void *visit(simple_instr_list_c *symbol);
   869     void *visit(simple_instr_list_c *symbol);
  1709 	return NULL;
  1852 	return NULL;
  1710 }
  1853 }
  1711 
  1854 
  1712 
  1855 
  1713 void *fill_candidate_datatypes_c::visit(function_invocation_c *symbol) {
  1856 void *fill_candidate_datatypes_c::visit(function_invocation_c *symbol) {
  1714 	function_declaration_c *f_decl;
  1857 	if      (NULL != symbol->formal_param_list)        symbol->   formal_param_list->accept(*this);
  1715 	list_c *parameter_list;
  1858 	else if (NULL != symbol->nonformal_param_list)     symbol->nonformal_param_list->accept(*this);
  1716 	list_c *parameter_candidate_datatypes;
       
  1717 	symbol_c *returned_parameter_type;
       
  1718 
       
  1719 	if (debug) std::cout << "function()\n";
       
  1720 
       
  1721 	function_symtable_t::iterator lower = function_symtable.lower_bound(symbol->function_name);
       
  1722 	function_symtable_t::iterator upper = function_symtable.upper_bound(symbol->function_name);
       
  1723 	/* If the name of the function being called is not found in the function symbol table, then this is an invalid call */
       
  1724 	/* Since the lexical parser already checks for this, then if this occurs then we have an internal compiler error. */
       
  1725 	if (lower == function_symtable.end()) ERROR;
       
  1726 	
       
  1727 	if (NULL != symbol->formal_param_list)
       
  1728 		parameter_list = (list_c *)symbol->formal_param_list;
       
  1729 	else if (NULL != symbol->nonformal_param_list)
       
  1730 		parameter_list = (list_c *)symbol->nonformal_param_list;
       
  1731 	else ERROR;
  1859 	else ERROR;
  1732 	
  1860 
  1733 	/* Fill in the candidate_datatypes lists of all the expressions used in the function call parameters */
  1861 	generic_function_call_t fcall_param = {
  1734 	parameter_list->accept(*this);
  1862 	/* fcall_param.function_name               = */ symbol->function_name,
  1735 
  1863 	/* fcall_param.nonformal_operand_list      = */ symbol->nonformal_param_list,
  1736 	/* Look for all compatible function declarations, and add their return datatypes 
  1864 	/* fcall_param.formal_operand_list         = */ symbol->formal_param_list,
  1737 	 * to the candidate_datatype list of this function invocation. 
  1865 	/* fcall_param.candidate_functions         = */ symbol->candidate_functions,
  1738 	 *
  1866 	/* fcall_param.called_function_declaration = */ symbol->called_function_declaration,
  1739 	 * If only one function exists, we add its return datatype to the candidate_datatype list,
  1867 	/* fcall_param.extensible_param_count      = */ symbol->extensible_param_count
  1740 	 * even if the parameters passed to it are invalid.
  1868 	};
  1741 	 * This guarantees that the remainder of the expression in which the function call is inserted
  1869 	handle_function_call(symbol, fcall_param);
  1742 	 * is treated as if the function call returns correctly, and therefore does not generate
  1870 
  1743 	 * spurious error messages.
  1871 	if (debug) std::cout << "function_invocation_c [" << symbol->candidate_datatypes.size() << "] result.\n";
  1744 	 * Even if the parameters to the function call are invalid, doing this is still safe, as the 
       
  1745 	 * expressions inside the function call will themselves have erros and will  guarantee that 
       
  1746 	 * compilation is aborted in stage3 (in print_datatypes_error_c).
       
  1747 	 */
       
  1748 	if (function_symtable.multiplicity(symbol->function_name) == 1) {
       
  1749 		f_decl = function_symtable.get_value(lower);
       
  1750 		returned_parameter_type = base_type(f_decl->type_name);
       
  1751 		symbol->candidate_functions.push_back(f_decl);
       
  1752 		symbol->candidate_datatypes.push_back(returned_parameter_type);
       
  1753 	}
       
  1754 	for(; lower != upper; lower++) {
       
  1755 		bool compatible = false;
       
  1756 		
       
  1757 		f_decl = function_symtable.get_value(lower);
       
  1758 		/* Check if function declaration in symbol_table is compatible with parameters */
       
  1759 		if (NULL != symbol->nonformal_param_list)  compatible=match_nonformal_call(symbol, f_decl);
       
  1760 		if (NULL != symbol->   formal_param_list)  compatible=   match_formal_call(symbol, f_decl);
       
  1761 		if (compatible) {
       
  1762 			/* Add the data type returned by the called functions. 
       
  1763 			 * However, only do this if this data type is not already present in the candidate_datatypes list_c
       
  1764 			 */
       
  1765 			unsigned int k;
       
  1766 			returned_parameter_type = base_type(f_decl->type_name);
       
  1767 			for(k = 0; k < symbol->candidate_datatypes.size(); k++) {
       
  1768 				if (is_type_equal(returned_parameter_type, symbol->candidate_datatypes[k]))
       
  1769 					break;
       
  1770 			}
       
  1771 			if (k >= symbol->candidate_datatypes.size()) {
       
  1772 				symbol->candidate_datatypes.push_back(returned_parameter_type);
       
  1773 				symbol->candidate_functions.push_back(f_decl);
       
  1774 			}
       
  1775 		}
       
  1776 	}
       
  1777 	if (debug) std::cout << "end_function() [" << symbol->candidate_datatypes.size() << "] result.\n";
       
  1778 	return NULL;
  1872 	return NULL;
  1779 }
  1873 }
  1780 
  1874 
  1781 
  1875 
  1782 
  1876