Continue adding support for semantic verification of JMP and RET.
--- a/absyntax/absyntax.def Thu Mar 01 10:28:27 2012 +0000
+++ b/absyntax/absyntax.def Fri Mar 02 12:53:41 2012 +0000
@@ -97,6 +97,12 @@
SYM_REF0(eno_param_c)
*/
+/* A class used to identify an entry (literal, variable, etc...) in the abstract syntax tree with an invalid data type */
+/* This is only used from stage3 onwards. Stages 1 and 2 will never create any instances of invalid_type_name_c */
+SYM_REF0(invalid_type_name_c)
+
+
+
/********************/
/* 2.1.6 - Pragmas */
/********************/
--- a/absyntax/absyntax.hh Thu Mar 01 10:28:27 2012 +0000
+++ b/absyntax/absyntax.hh Fri Mar 02 12:53:41 2012 +0000
@@ -77,8 +77,13 @@
int last_column;
const char *last_file; /* filename referenced by last line/column */
long int last_order; /* relative order in which it is read by lexcial analyser */
- symbol_c * datatype; /* data type of the expression/literal/etc. Filled in stage3 by narrow_candidate_datatypes_c */
std::vector <symbol_c *> candidate_datatypes; /* All possible data types the expression/literal/etc. may take. Filled in stage3 by fill_candidate_datatypes_c class */
+ /* Data type of the expression/literal/etc. Filled in stage3 by narrow_candidate_datatypes_c
+ * If set to NULL, it means it has not yet been evaluated.
+ * If it points to an object of type invalid_type_name_c, it means it is invalid.
+ * Otherwise, it points to an object of the apropriate data type (e.g. int_type_name_c, bool_type_name_c, ...)
+ */
+ symbol_c *datatype;
public:
--- a/absyntax_utils/Makefile.am Thu Mar 01 10:28:27 2012 +0000
+++ b/absyntax_utils/Makefile.am Fri Mar 02 12:53:41 2012 +0000
@@ -13,6 +13,7 @@
function_param_iterator.cc \
get_function_type.cc \
get_sizeof_datatype.cc \
+ search_il_label.cc \
search_base_type.cc \
search_constant_type.cc \
search_expression_type.cc \
--- a/absyntax_utils/Makefile.in Thu Mar 01 10:28:27 2012 +0000
+++ b/absyntax_utils/Makefile.in Fri Mar 02 12:53:41 2012 +0000
@@ -78,8 +78,8 @@
function_call_iterator.$(OBJEXT) \
function_call_param_iterator.$(OBJEXT) \
function_param_iterator.$(OBJEXT) get_function_type.$(OBJEXT) \
- get_sizeof_datatype.$(OBJEXT) search_base_type.$(OBJEXT) \
- search_constant_type.$(OBJEXT) \
+ get_sizeof_datatype.$(OBJEXT) search_il_label.$(OBJEXT) \
+ search_base_type.$(OBJEXT) search_constant_type.$(OBJEXT) \
search_expression_type.$(OBJEXT) \
search_fb_instance_decl.$(OBJEXT) search_fb_typedecl.$(OBJEXT) \
search_varfb_instance_type.$(OBJEXT) \
@@ -213,6 +213,7 @@
function_param_iterator.cc \
get_function_type.cc \
get_sizeof_datatype.cc \
+ search_il_label.cc \
search_base_type.cc \
search_constant_type.cc \
search_expression_type.cc \
@@ -319,6 +320,7 @@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/search_expression_type.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/search_fb_instance_decl.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/search_fb_typedecl.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/search_il_label.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/search_var_instance_decl.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/search_varfb_instance_type.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/spec_init_separator.Po@am__quote@
--- a/absyntax_utils/absyntax_utils.hh Thu Mar 01 10:28:27 2012 +0000
+++ b/absyntax_utils/absyntax_utils.hh Fri Mar 02 12:53:41 2012 +0000
@@ -120,7 +120,7 @@
#include "add_en_eno_param_decl.hh"
#include "get_sizeof_datatype.hh"
#include "get_function_type.h"
-
+#include "search_il_label.hh"
/***********************************************************************/
/***********************************************************************/
--- a/absyntax_utils/search_constant_type.cc Thu Mar 01 10:28:27 2012 +0000
+++ b/absyntax_utils/search_constant_type.cc Fri Mar 02 12:53:41 2012 +0000
@@ -133,6 +133,12 @@
return (void *)value_type;
}
+
+
+
+invalid_type_name_c search_constant_type_c::invalid_type_name;
+
+
real_type_name_c search_constant_type_c::real_type_name;
sint_type_name_c search_constant_type_c::sint_type_name;
lint_type_name_c search_constant_type_c::lint_type_name;
--- a/absyntax_utils/search_constant_type.hh Thu Mar 01 10:28:27 2012 +0000
+++ b/absyntax_utils/search_constant_type.hh Fri Mar 02 12:53:41 2012 +0000
@@ -30,6 +30,14 @@
*
*/
+/* NOTE: The use of this visitor class is now deprecated.
+ * The new version of stage3 data type checking adds an entry to
+ * every relevant object in the abstract syntax tree defining
+ * the data type of that object. Please use that instead!
+ */
+
+
+
/* Determine the data type of a specific constant or variable.
* A reference to the relevant type definition is returned.
*
@@ -49,6 +57,10 @@
class search_constant_type_c: public search_visitor_c {
public:
+ /* object used to identify an entry in the abstract syntax tree with an invalid data type */
+ /* This is only used from stage3 onwards. Stages 1 and 2 will never create any instances of invalid_type_name_c */
+ static invalid_type_name_c invalid_type_name;
+
/**********************/
/* B.1.3 - Data types */
/**********************/
--- a/stage3/datatype_functions.cc Thu Mar 01 10:28:27 2012 +0000
+++ b/stage3/datatype_functions.cc Fri Mar 02 12:53:41 2012 +0000
@@ -228,6 +228,20 @@
+/* intersect the candidate_datatype lists of all prev_il_intructions, and set the local candidate_datatype list to the result! */
+void intersect_prev_candidate_datatype_lists(il_instruction_c *symbol) {
+ if (symbol->prev_il_instruction.empty())
+ return;
+
+ copy_candidate_datatype_list(symbol->prev_il_instruction[0] /*from*/, symbol /*to*/);
+ for (unsigned int i = 1; i < symbol->prev_il_instruction.size(); i++) {
+ intersect_candidate_datatype_list(symbol /*origin, dest.*/, symbol->prev_il_instruction[i] /*with*/);
+ }
+}
+
+
+
+
/* A helper function... */
bool is_ANY_ELEMENTARY_type(symbol_c *type_symbol) {
if (type_symbol == NULL) {return false;}
@@ -544,16 +558,30 @@
-bool is_type_equal(symbol_c *first_type, symbol_c *second_type)
-{
- if (first_type == NULL || second_type == NULL) {
- return false;
- }
- if (is_ANY_ELEMENTARY_type(first_type)) {
- if (typeid(*first_type) == typeid(*second_type))
- return true;
- } else /* ANY_DERIVED */
- return (first_type == second_type);
-
- return false;
-}
+bool is_type_equal(symbol_c *first_type, symbol_c *second_type) {
+ if ((NULL == first_type) || (NULL == second_type))
+ return false;
+ if (typeid(* first_type) == typeid(invalid_type_name_c))
+ return false;
+ if (typeid(*second_type) == typeid(invalid_type_name_c))
+ return false;
+
+ if (is_ANY_ELEMENTARY_type(first_type)) {
+ if (typeid(*first_type) == typeid(*second_type))
+ return true;
+ } else /* ANY_DERIVED */
+ return (first_type == second_type);
+
+ return false;
+}
+
+
+
+bool is_type_valid(symbol_c *type) {
+ if (NULL == type)
+ return false;
+ if (typeid(*type) == typeid(invalid_type_name_c))
+ return false;
+
+ return true;
+}
--- a/stage3/datatype_functions.hh Thu Mar 01 10:28:27 2012 +0000
+++ b/stage3/datatype_functions.hh Fri Mar 02 12:53:41 2012 +0000
@@ -154,6 +154,10 @@
*/
void intersect_candidate_datatype_list(symbol_c *list1 /*origin, dest.*/, symbol_c *list2 /*with*/);
+/* intersect the candidate_datatype lists of all prev_il_intructions, and set the local candidate_datatype list to the result! */
+void intersect_prev_candidate_datatype_lists(il_instruction_c *symbol);
+
+
/* A helper function... */
bool is_ANY_ELEMENTARY_type (symbol_c *type_symbol);
@@ -206,8 +210,9 @@
bool is_type_equal(symbol_c *first_type, symbol_c *second_type);
-
-// typedef bool (*helper_function_t) (symbol_c *type_symbol); /* a pointer to a function! */
+bool is_type_valid(symbol_c *type);
+
+
#endif /* _HELPER_FUNCTIONS_HH_ */
--- a/stage3/fill_candidate_datatypes.cc Thu Mar 01 10:28:27 2012 +0000
+++ b/stage3/fill_candidate_datatypes.cc Fri Mar 02 12:53:41 2012 +0000
@@ -565,7 +565,9 @@
/************************/
void *fill_candidate_datatypes_c::visit(duration_c *symbol) {
/* TODO: check whether the literal follows the rules specified in section '2.2.3.1 Duration' of the standard! */
- symbol->candidate_datatypes.push_back(symbol->type_name);
+
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::time_type_name);
+// symbol->candidate_datatypes.push_back(symbol->type_name);
if (debug) std::cout << "TIME_LITERAL [" << symbol->candidate_datatypes.size() << "]\n";
return NULL;
}
@@ -800,6 +802,7 @@
// void *visit(instruction_list_c *symbol);
+
/* | label ':' [il_incomplete_instruction] eol_list */
// SYM_REF2(il_instruction_c, label, il_instruction)
// void *visit(instruction_list_c *symbol);
@@ -808,16 +811,14 @@
/* This empty/null il_instruction does not change the value of the current/default IL variable.
* So it inherits the candidate_datatypes from it's previous IL instructions!
*/
- if (!symbol->prev_il_instruction.empty()) {
- copy_candidate_datatype_list(symbol->prev_il_instruction[0] /*from*/, symbol /*to*/);
- for (unsigned int i = 1; i < symbol->prev_il_instruction.size(); i++) {
- intersect_candidate_datatype_list(symbol /*origin, dest.*/, symbol->prev_il_instruction[i] /*with*/);
- }
- }
+ intersect_prev_candidate_datatype_lists(symbol);
} else {
- if (symbol->prev_il_instruction.size() > 1) ERROR; /* This assertion is only valid for now. Remove it once flow_control_analysis_c is complete */
+// if (symbol->prev_il_instruction.size() > 1) ERROR; /* This assertion is only valid for now. Remove it once flow_control_analysis_c is complete */
+ il_instruction_c fake_prev_il_instruction = *symbol;
+ intersect_prev_candidate_datatype_lists(&fake_prev_il_instruction);
+
if (symbol->prev_il_instruction.size() == 0) prev_il_instruction = NULL;
- else prev_il_instruction = symbol->prev_il_instruction[0];
+ else prev_il_instruction = &fake_prev_il_instruction;
symbol->il_instruction->accept(*this);
prev_il_instruction = NULL;
@@ -855,7 +856,6 @@
*
* However, if no further paramters are given, then il_operand_list will be NULL, and we will
* need to create a new object to hold the pointer to prev_il_instruction.
- * This change will also be undone later in print_datatypes_error_c.
*/
if (NULL == symbol->il_operand_list) symbol->il_operand_list = new il_operand_list_c;
if (NULL == symbol->il_operand_list) ERROR;
@@ -1022,7 +1022,7 @@
// SYM_REF1(il_simple_instruction_c, il_simple_instruction, symbol_c *prev_il_instruction;)
void *fill_candidate_datatypes_c::visit(il_simple_instruction_c *symbol) {
- if (symbol->prev_il_instruction.size() > 1) ERROR; /* This assertion is only valid for now. Remove it once flow_control_analysis_c is complete */
+ if (symbol->prev_il_instruction.size() > 1) ERROR; /* There should be no labeled insructions inside an IL expression! */
if (symbol->prev_il_instruction.size() == 0) prev_il_instruction = NULL;
else prev_il_instruction = symbol->prev_il_instruction[0];
symbol->il_simple_instruction->accept(*this);
--- a/stage3/flow_control_analysis.cc Thu Mar 01 10:28:27 2012 +0000
+++ b/stage3/flow_control_analysis.cc Fri Mar 02 12:53:41 2012 +0000
@@ -113,6 +113,8 @@
static int debug = 0;
flow_control_analysis_c::flow_control_analysis_c(symbol_c *ignore) {
+ prev_il_instruction = NULL;
+ curr_il_instruction = NULL;
}
flow_control_analysis_c::~flow_control_analysis_c(void) {
@@ -127,11 +129,11 @@
/* B 1.5.1 Functions */
/*********************/
void *flow_control_analysis_c::visit(function_declaration_c *symbol) {
- search_varfb_instance_type = new search_varfb_instance_type_c(symbol);
+ search_il_label = new search_il_label_c(symbol);
if (debug) printf("Doing flow control analysis in body of function %s\n", ((token_c *)(symbol->derived_function_name))->value);
symbol->function_body->accept(*this);
- delete search_varfb_instance_type;
- search_varfb_instance_type = NULL;
+ delete search_il_label;
+ search_il_label = NULL;
return NULL;
}
@@ -139,11 +141,11 @@
/* B 1.5.2 Function blocks */
/***************************/
void *flow_control_analysis_c::visit(function_block_declaration_c *symbol) {
- search_varfb_instance_type = new search_varfb_instance_type_c(symbol);
+ search_il_label = new search_il_label_c(symbol);
if (debug) printf("Doing flow control analysis in body of FB %s\n", ((token_c *)(symbol->fblock_name))->value);
symbol->fblock_body->accept(*this);
- delete search_varfb_instance_type;
- search_varfb_instance_type = NULL;
+ delete search_il_label;
+ search_il_label = NULL;
return NULL;
}
@@ -151,11 +153,11 @@
/* B 1.5.3 Programs */
/********************/
void *flow_control_analysis_c::visit(program_declaration_c *symbol) {
- search_varfb_instance_type = new search_varfb_instance_type_c(symbol);
+ search_il_label = new search_il_label_c(symbol);
if (debug) printf("Doing flow control analysis in body of program %s\n", ((token_c *)(symbol->program_type_name))->value);
symbol->function_block_body->accept(*this);
- delete search_varfb_instance_type;
- search_varfb_instance_type = NULL;
+ delete search_il_label;
+ search_il_label = NULL;
return NULL;
}
@@ -181,7 +183,9 @@
for(int i = 0; i < symbol->n; i++) {
prev_il_instruction = NULL;
if (i > 0) prev_il_instruction = symbol->elements[i-1];
- symbol->elements[i]->accept(*this);
+ curr_il_instruction = symbol->elements[i];
+ curr_il_instruction->accept(*this);
+ curr_il_instruction = NULL;
}
return NULL;
}
@@ -190,34 +194,28 @@
// SYM_REF2(il_instruction_c, label, il_instruction)
// void *visit(instruction_list_c *symbol);
void *flow_control_analysis_c::visit(il_instruction_c *symbol) {
- symbol->prev_il_instruction.push_back(prev_il_instruction);
- /* TODO: handle labels correctly!
- *
- * Don't forget to handle multiple consecutive lables too!
- * label2:
- * label3:
- * label4:
- * LD I
- */
- /* NOTE: the following recursive call will mess up the value in the
- * this->prev_il_instruction variable, so be sure not to use it
- * after the return of symbol->il_instruction->accept(*this);
- */
- /* check if it is an il_expression_c, and if so, handle it correctly */
+ if (NULL != prev_il_instruction)
+ symbol->prev_il_instruction.push_back(prev_il_instruction);
+
+ /* check if it is an il_expression_c, or a JMP[C[N]] and if so, handle it correctly */
if (NULL != symbol->il_instruction)
symbol->il_instruction->accept(*this);
return NULL;
}
-#if 0
+
+/* | il_simple_operator [il_operand] */
+// SYM_REF2(il_simple_operation_c, il_simple_operator, il_operand)
+// void *flow_control_analysis_c::visit(il_simple_operation_c *symbol)
+
+
+
/* | function_name [il_operand_list] */
/* NOTE: The parameters 'called_function_declaration' and 'extensible_param_count' are used to pass data between the stage 3 and stage 4. */
// SYM_REF2(il_function_call_c, function_name, il_operand_list, symbol_c *called_function_declaration; int extensible_param_count;)
-void *flow_control_analysis_c::visit(il_function_call_c *symbol) {
- return NULL;
-}
-#endif
+// void *flow_control_analysis_c::visit(il_function_call_c *symbol)
+
/* | il_expr_operator '(' [il_operand] eol_list [simple_instr_list] ')' */
// SYM_REF3(il_expression_c, il_expr_operator, il_operand, simple_instr_list);
@@ -226,13 +224,28 @@
/* nothing to do... */
return NULL;
+ symbol_c *save_prev_il_instruction = prev_il_instruction;
prev_il_instruction = symbol->il_operand;
symbol->simple_instr_list->accept(*this);
- return NULL;
-}
-
-
-#if 0
+ prev_il_instruction = save_prev_il_instruction;
+ return NULL;
+}
+
+
+/* il_jump_operator label */
+// SYM_REF2(il_jump_operation_c, il_jump_operator, label)
+void *flow_control_analysis_c::visit(il_jump_operation_c *symbol) {
+ /* search for the il_instruction_c containing the label */
+ il_instruction_c *destination = search_il_label->find_label(symbol->label);
+
+ /* TODO: for JMP and RET (unconditional) instructions, make sure the next IL instruction does not point back! */
+ /* add, to that il_instruction's list of prev_il_intsructions, the curr_il_instruction */
+ if (NULL != destination)
+ destination->prev_il_instruction.push_back(curr_il_instruction);
+ return NULL;
+}
+
+
/* il_call_operator prev_declared_fb_name
* | il_call_operator prev_declared_fb_name '(' ')'
* | il_call_operator prev_declared_fb_name '(' eol_list ')'
@@ -241,18 +254,14 @@
*/
/* NOTE: The parameter 'called_fb_declaration'is used to pass data between stage 3 and stage4 (although currently it is not used in stage 4 */
// SYM_REF4(il_fb_call_c, il_call_operator, fb_name, il_operand_list, il_param_list, symbol_c *called_fb_declaration)
-void *flow_control_analysis_c::visit(il_fb_call_c *symbol) {
- return NULL;
-}
+// void *flow_control_analysis_c::visit(il_fb_call_c *symbol)
/* | function_name '(' eol_list [il_param_list] ')' */
/* NOTE: The parameter 'called_function_declaration' is used to pass data between the stage 3 and stage 4. */
// SYM_REF2(il_formal_funct_call_c, function_name, il_param_list, symbol_c *called_function_declaration; int extensible_param_count;)
-void *flow_control_analysis_c::visit(il_formal_funct_call_c *symbol) {
- return NULL;
-}
-#endif
+// void *flow_control_analysis_c::visit(il_formal_funct_call_c *symbol)
+
// void *visit(il_operand_list_c *symbol);
@@ -268,7 +277,8 @@
// SYM_REF1(il_simple_instruction_c, il_simple_instruction, symbol_c *prev_il_instruction;)
void *flow_control_analysis_c::visit(il_simple_instruction_c*symbol) {
- symbol->prev_il_instruction.push_back(prev_il_instruction);
+ if (NULL != prev_il_instruction)
+ symbol->prev_il_instruction.push_back(prev_il_instruction);
return NULL;
}
@@ -281,3 +291,54 @@
+
+/*******************/
+/* B 2.2 Operators */
+/*******************/
+// void *visit( LD_operator_c *symbol);
+// void *visit( LDN_operator_c *symbol);
+// void *visit( ST_operator_c *symbol);
+// void *visit( STN_operator_c *symbol);
+// void *visit( NOT_operator_c *symbol);
+// void *visit( S_operator_c *symbol);
+// void *visit( R_operator_c *symbol);
+// void *visit( S1_operator_c *symbol);
+// void *visit( R1_operator_c *symbol);
+// void *visit( CLK_operator_c *symbol);
+// void *visit( CU_operator_c *symbol);
+// void *visit( CD_operator_c *symbol);
+// void *visit( PV_operator_c *symbol);
+// void *visit( IN_operator_c *symbol);
+// void *visit( PT_operator_c *symbol);
+// void *visit( AND_operator_c *symbol);
+// void *visit( OR_operator_c *symbol);
+// void *visit( XOR_operator_c *symbol);
+// void *visit( ANDN_operator_c *symbol);
+// void *visit( ORN_operator_c *symbol);
+// void *visit( XORN_operator_c *symbol);
+// void *visit( ADD_operator_c *symbol);
+// void *visit( SUB_operator_c *symbol);
+// void *visit( MUL_operator_c *symbol);
+// void *visit( DIV_operator_c *symbol);
+// void *visit( MOD_operator_c *symbol);
+// void *visit( GT_operator_c *symbol);
+// void *visit( GE_operator_c *symbol);
+// void *visit( EQ_operator_c *symbol);
+// void *visit( LT_operator_c *symbol);
+// void *visit( LE_operator_c *symbol);
+// void *visit( NE_operator_c *symbol);
+// void *visit( CAL_operator_c *symbol);
+// void *visit( CALC_operator_c *symbol);
+// void *visit(CALCN_operator_c *symbol);
+// void *visit( RET_operator_c *symbol);
+// void *visit( RETC_operator_c *symbol);
+// void *visit(RETCN_operator_c *symbol);
+// void *visit( JMP_operator_c *symbol);
+// void *visit( JMPC_operator_c *symbol);
+// void *visit(JMPCN_operator_c *symbol);
+
+/* Symbol class handled together with function call checks */
+// void *visit(il_assign_operator_c *symbol, variable_name);
+/* Symbol class handled together with function call checks */
+// void *visit(il_assign_operator_c *symbol, option, variable_name);
+
--- a/stage3/flow_control_analysis.hh Thu Mar 01 10:28:27 2012 +0000
+++ b/stage3/flow_control_analysis.hh Fri Mar 02 12:53:41 2012 +0000
@@ -48,8 +48,9 @@
class flow_control_analysis_c: public iterator_visitor_c {
private:
- search_varfb_instance_type_c *search_varfb_instance_type;
+ search_il_label_c *search_il_label;
symbol_c *prev_il_instruction;
+ symbol_c *curr_il_instruction;
public:
flow_control_analysis_c(symbol_c *ignore);
@@ -89,6 +90,7 @@
// void *visit(il_simple_operation_c *symbol);
// void *visit(il_function_call_c *symbol);
void *visit(il_expression_c *symbol);
+ void *visit(il_jump_operation_c *symbol);
// void *visit(il_fb_call_c *symbol);
// void *visit(il_formal_funct_call_c *symbol);
// void *visit(il_operand_list_c *symbol);
@@ -101,49 +103,48 @@
/*******************/
/* B 2.2 Operators */
/*******************/
- /*
- void *visit(LD_operator_c *symbol);
- void *visit(LDN_operator_c *symbol);
- void *visit(ST_operator_c *symbol);
- void *visit(STN_operator_c *symbol);
- void *visit(NOT_operator_c *symbol);
- void *visit(S_operator_c *symbol);
- void *visit(R_operator_c *symbol);
- void *visit(S1_operator_c *symbol);
- void *visit(R1_operator_c *symbol);
- void *visit(CLK_operator_c *symbol);
- void *visit(CU_operator_c *symbol);
- void *visit(CD_operator_c *symbol);
- void *visit(PV_operator_c *symbol);
- void *visit(IN_operator_c *symbol);
- void *visit(PT_operator_c *symbol);
- void *visit(AND_operator_c *symbol);
- void *visit(OR_operator_c *symbol);
- void *visit(XOR_operator_c *symbol);
- void *visit(ANDN_operator_c *symbol);
- void *visit(ORN_operator_c *symbol);
- void *visit(XORN_operator_c *symbol);
- void *visit(ADD_operator_c *symbol);
- void *visit(SUB_operator_c *symbol);
- void *visit(MUL_operator_c *symbol);
- void *visit(DIV_operator_c *symbol);
- void *visit(MOD_operator_c *symbol);
- void *visit(GT_operator_c *symbol);
- void *visit(GE_operator_c *symbol);
- void *visit(EQ_operator_c *symbol);
- void *visit(LT_operator_c *symbol);
- void *visit(LE_operator_c *symbol);
- void *visit(NE_operator_c *symbol);
- void *visit(CAL_operator_c *symbol);
- void *visit(CALC_operator_c *symbol);
- void *visit(CALCN_operator_c *symbol);
- void *visit(RET_operator_c *symbol);
- void *visit(RETC_operator_c *symbol);
- void *visit(RETCN_operator_c *symbol);
- void *visit(JMP_operator_c *symbol);
- void *visit(JMPC_operator_c *symbol);
- void *visit(JMPCN_operator_c *symbol);
- */
+// void *visit( LD_operator_c *symbol);
+// void *visit( LDN_operator_c *symbol);
+// void *visit( ST_operator_c *symbol);
+// void *visit( STN_operator_c *symbol);
+// void *visit( NOT_operator_c *symbol);
+// void *visit( S_operator_c *symbol);
+// void *visit( R_operator_c *symbol);
+// void *visit( S1_operator_c *symbol);
+// void *visit( R1_operator_c *symbol);
+// void *visit( CLK_operator_c *symbol);
+// void *visit( CU_operator_c *symbol);
+// void *visit( CD_operator_c *symbol);
+// void *visit( PV_operator_c *symbol);
+// void *visit( IN_operator_c *symbol);
+// void *visit( PT_operator_c *symbol);
+// void *visit( AND_operator_c *symbol);
+// void *visit( OR_operator_c *symbol);
+// void *visit( XOR_operator_c *symbol);
+// void *visit( ANDN_operator_c *symbol);
+// void *visit( ORN_operator_c *symbol);
+// void *visit( XORN_operator_c *symbol);
+// void *visit( ADD_operator_c *symbol);
+// void *visit( SUB_operator_c *symbol);
+// void *visit( MUL_operator_c *symbol);
+// void *visit( DIV_operator_c *symbol);
+// void *visit( MOD_operator_c *symbol);
+// void *visit( GT_operator_c *symbol);
+// void *visit( GE_operator_c *symbol);
+// void *visit( EQ_operator_c *symbol);
+// void *visit( LT_operator_c *symbol);
+// void *visit( LE_operator_c *symbol);
+// void *visit( NE_operator_c *symbol);
+// void *visit( CAL_operator_c *symbol);
+// void *visit( CALC_operator_c *symbol);
+// void *visit(CALCN_operator_c *symbol);
+// void *visit( RET_operator_c *symbol);
+// void *visit( RETC_operator_c *symbol);
+// void *visit(RETCN_operator_c *symbol);
+// void *visit( JMP_operator_c *symbol);
+// void *visit( JMPC_operator_c *symbol);
+// void *visit(JMPCN_operator_c *symbol);
+
/* Symbol class handled together with function call checks */
// void *visit(il_assign_operator_c *symbol, variable_name);
/* Symbol class handled together with function call checks */
--- a/stage3/narrow_candidate_datatypes.cc Thu Mar 01 10:28:27 2012 +0000
+++ b/stage3/narrow_candidate_datatypes.cc Fri Mar 02 12:53:41 2012 +0000
@@ -57,15 +57,38 @@
/* Only set the symbol's desired datatype to 'datatype' if that datatype is in the candidate_datatype list */
static void set_datatype(symbol_c *datatype, symbol_c *symbol) {
- symbol->datatype = NULL;
- if (search_in_candidate_datatype_list(datatype, symbol->candidate_datatypes) >= 0)
- symbol->datatype = datatype;
+
+ /* If we are trying to set to the undefined type, and the symbol's datatype has already been set to something else,
+ * we abort the compoiler as I don't think this should ever occur.
+ * However, I (Mario) am not too sure of this, so if the compiler ever aborts here, please analyse the situation
+ * carefully as it might be perfectly legal and something I have missed!
+ */
+ if ((NULL == datatype) && (NULL != symbol->datatype)) ERROR;
+
+ if ((NULL == datatype) && (NULL == symbol->datatype)) return;
+
+ if (search_in_candidate_datatype_list(datatype, symbol->candidate_datatypes) < 0)
+ symbol->datatype = &(search_constant_type_c::invalid_type_name);
+ else {
+ if (NULL == symbol->datatype)
+ /* not yet set to anything, so we set it to the requested data type */
+ symbol->datatype = datatype;
+ else {
+ /* had already been set previously to some data type. Let's check if they are the same! */
+ if (!is_type_equal(symbol->datatype, datatype))
+ symbol->datatype = &(search_constant_type_c::invalid_type_name);
+// else
+ /* we leave it unchanged, as it is the same as the requested data type! */
+ }
+ }
}
/* Only set the symbol's desired datatype to 'datatype' if that datatype is in the candidate_datatype list */
-static void set_datatype_in_prev_il_instruction(symbol_c *datatype, il_instruction_c *symbol) {
+// static void set_datatype_in_prev_il_instructions(symbol_c *datatype, std::vector <symbol_c *> prev_il_instructions) {
+static void set_datatype_in_prev_il_instructions(symbol_c *datatype, il_instruction_c *symbol) {
+ if (NULL == symbol) ERROR;
for (unsigned int i = 0; i < symbol->prev_il_instruction.size(); i++)
set_datatype(datatype, symbol->prev_il_instruction[i]);
}
@@ -276,7 +299,7 @@
}
symbol_c *fb_decl = il_operand->datatype;
- if (NULL == prev_il_instruction) {
+ if (0 == fake_prev_il_instruction->prev_il_instruction.size()) {
/* This IL implicit FB call (e.g. CLK ton_var) is not preceded by another IL instruction
* (or list of instructions) that will set the IL current/default value.
* We cannot proceed verifying type compatibility of something that does not exist.
@@ -286,9 +309,9 @@
if (NULL == fb_decl) {
/* the il_operand is a not FB instance */
- /* so we simply pass on the required datatype to the prev_il_instruction */
- /* The invalid FB invocation will be caught by the print_datatypes_error_c by analysing NULL value in il_operand->datatype! */
- prev_il_instruction->datatype = il_instruction->datatype;
+ /* so we simply pass on the required datatype to the prev_il_instructions */
+ /* The invalid FB invocation will be caught in the print_datatypes_error_c by analysing NULL value in il_operand->datatype! */
+ set_datatype_in_prev_il_instructions(il_instruction->datatype, fake_prev_il_instruction);
return NULL;
}
@@ -302,8 +325,15 @@
* would be changed to the IL instruction coming before the current prev_il_instruction! => things would get all messed up!)
* The easiest way to work around this is to simply use a new object, and copy the relevant details to that object!
*/
- symbol_c param_value = *prev_il_instruction;
-
+printf("XX::narrow_candidate_datatypes_c::narrow_implicit_il_fb_call(): fake_prev_il_instruction->candidate_datatypes.size() = %d\n",fake_prev_il_instruction->candidate_datatypes.size());
+printf("XX::narrow_candidate_datatypes_c::narrow_implicit_il_fb_call(): fake_prev_il_instruction->candidate_datatypes[0] = %p\n",fake_prev_il_instruction->candidate_datatypes[0]);
+ symbol_c param_value = *fake_prev_il_instruction; /* copy the candidate_datatypes list ! */
+printf("XX::narrow_candidate_datatypes_c::narrow_implicit_il_fb_call(): param_value.candidate_datatypes.size() = %d\n",param_value.candidate_datatypes.size());
+printf("XX::narrow_candidate_datatypes_c::narrow_implicit_il_fb_call(): param_value.candidate_datatypes[0] = %p\n",param_value.candidate_datatypes[0]);
+printf("00::narrow_candidate_datatypes_c::narrow_implicit_il_fb_call(): search_constant_type::time_type_name = %p\n", &search_constant_type_c::time_type_name);
+printf("00::narrow_candidate_datatypes_c::narrow_implicit_il_fb_call(): search_constant_type::invalid_type_name = %p\n", &search_constant_type_c::invalid_type_name);
+
+printf("11::narrow_candidate_datatypes_c::narrow_implicit_il_fb_call(): param_value.datatype = %p\n", param_value.datatype);
identifier_c variable_name(param_name);
// SYM_REF1(il_assign_operator_c, variable_name)
il_assign_operator_c il_assign_operator(&variable_name);
@@ -314,6 +344,7 @@
// SYM_REF4(il_fb_call_c, il_call_operator, fb_name, il_operand_list, il_param_list, symbol_c *called_fb_declaration)
CAL_operator_c CAL_operator;
il_fb_call_c il_fb_call(&CAL_operator, il_operand, NULL, &il_param_list);
+printf("22::narrow_candidate_datatypes_c::narrow_implicit_il_fb_call(): param_value.datatype = %p\n", param_value.datatype);
/* A FB call does not return any datatype, but the IL instructions that come after this
* FB call may require a specific datatype in the il current/default variable,
@@ -326,6 +357,7 @@
// copy_candidate_datatype_list(il_instruction/*from*/, &il_fb_call/*to*/);
il_fb_call.called_fb_declaration = called_fb_declaration;
il_fb_call.accept(*this);
+printf("33::narrow_candidate_datatypes_c::narrow_implicit_il_fb_call(): param_value.datatype = %p\n", param_value.datatype);
/* set the required datatype of the previous IL instruction! */
/* NOTE:
@@ -338,7 +370,7 @@
* This means that we have two consumers/users for the same value.
* We must therefore check whether the datatype required by the IL instructions following this FB call
* is the same as that required for the first parameter. If not, then we have a semantic error,
- * and we set it to NULL.
+ * and we set it to invalid_type_name.
*
* However, we only do that if:
* - The IL instruction that comes after this IL FB call actually asked this FB call for a specific
@@ -348,9 +380,11 @@
* FB call must be left unchanged!
*/
if ((NULL == il_instruction->datatype) || (is_type_equal(param_value.datatype, il_instruction->datatype))) {
- prev_il_instruction->datatype = param_value.datatype;
+printf("44::narrow_candidate_datatypes_c::narrow_implicit_il_fb_call(): param_value.datatype = %p\n", param_value.datatype);
+ set_datatype_in_prev_il_instructions(param_value.datatype, fake_prev_il_instruction);
} else {
- prev_il_instruction->datatype = NULL;
+printf("55::narrow_candidate_datatypes_c::narrow_implicit_il_fb_call(): param_value.datatype = %p\n", param_value.datatype);
+ set_datatype_in_prev_il_instructions(&search_constant_type_c::invalid_type_name, fake_prev_il_instruction);
}
return NULL;
}
@@ -510,14 +544,21 @@
void *narrow_candidate_datatypes_c::visit(il_instruction_c *symbol) {
if (NULL == symbol->il_instruction) {
/* this empty/null il_instruction cannot generate the desired datatype. We pass on the request to the previous il instruction. */
- set_datatype_in_prev_il_instruction(symbol->datatype, symbol);
+ set_datatype_in_prev_il_instructions(symbol->datatype, symbol);
} else {
+ il_instruction_c tmp_prev_il_instruction(NULL, NULL);
+ /* the narrow algorithm will need access to the intersected candidate_datatype lists of all prev_il_instructions, as well as the
+ * list of the prev_il_instructions.
+ * Instead of creating two 'global' (within the class) variables, we create a single il_instruction_c variable (fake_prev_il_instruction),
+ * and shove that data into this single variable.
+ */
+ tmp_prev_il_instruction.prev_il_instruction = symbol->prev_il_instruction;
+ intersect_prev_candidate_datatype_lists(&tmp_prev_il_instruction);
/* Tell the il_instruction the datatype that it must generate - this was chosen by the next il_instruction (remember: we are iterating backwards!) */
- if (symbol->prev_il_instruction.size() > 1) ERROR; /* This assertion is only valid for now. Remove it once flow_control_analysis_c is complete */
- if (symbol->prev_il_instruction.size() == 0) prev_il_instruction = NULL;
- else prev_il_instruction = symbol->prev_il_instruction[0];
+ fake_prev_il_instruction = &tmp_prev_il_instruction;
+ symbol->il_instruction->datatype = symbol->datatype;
symbol->il_instruction->accept(*this);
- prev_il_instruction = NULL;
+ fake_prev_il_instruction = NULL;
}
return NULL;
}
@@ -552,12 +593,10 @@
* need to create a new object to hold the pointer to prev_il_instruction.
* This change will also be undone later in print_datatypes_error_c.
*/
- symbol_c param_value;
+ symbol_c param_value = *fake_prev_il_instruction; /* copy the candidate_datatypes list */
if (NULL == symbol->il_operand_list) symbol->il_operand_list = new il_operand_list_c;
if (NULL == symbol->il_operand_list) ERROR;
- if (NULL != prev_il_instruction)
- param_value = *prev_il_instruction;
((list_c *)symbol->il_operand_list)->insert_element(¶m_value, 0);
generic_function_call_t fcall_param = {
@@ -571,8 +610,7 @@
};
narrow_function_invocation(symbol, fcall_param);
- if (NULL != prev_il_instruction)
- prev_il_instruction->datatype = param_value.datatype;
+ set_datatype_in_prev_il_instructions(param_value.datatype, fake_prev_il_instruction);
/* Undo the changes to the abstract syntax tree we made above... */
((list_c *)symbol->il_operand_list)->remove_element(0);
@@ -596,10 +634,10 @@
/* now give the parenthesised IL list a chance to narrow the datatypes */
/* The datatype that is must return was set by the call symbol->il_expr_operator->accept(*this) */
- symbol_c *save_prev_il_instruction = prev_il_instruction; /*this is not really necessary, but lets play it safe */
+ il_instruction_c *save_fake_prev_il_instruction = fake_prev_il_instruction; /*this is not really necessary, but lets play it safe */
symbol->simple_instr_list->accept(*this);
- prev_il_instruction = save_prev_il_instruction;
-return NULL;
+ fake_prev_il_instruction = save_fake_prev_il_instruction;
+ return NULL;
}
@@ -664,12 +702,23 @@
// SYM_REF1(il_simple_instruction_c, il_simple_instruction, symbol_c *prev_il_instruction;)
void *narrow_candidate_datatypes_c::visit(il_simple_instruction_c *symbol) {
- if (symbol->prev_il_instruction.size() > 1) ERROR; /* This assertion is only valid for now. Remove it once flow_control_analysis_c is complete */
- if (symbol->prev_il_instruction.size() == 0) prev_il_instruction = NULL;
- else prev_il_instruction = symbol->prev_il_instruction[0];
+ if (symbol->prev_il_instruction.size() > 1) ERROR; /* There should be no labeled insructions inside an IL expression! */
+
+ il_instruction_c tmp_prev_il_instruction(NULL, NULL);
+ /* the narrow algorithm will need access to the intersected candidate_datatype lists of all prev_il_instructions, as well as the
+ * list of the prev_il_instructions.
+ * Instead of creating two 'global' (within the class) variables, we create a single il_instruction_c variable (fake_prev_il_instruction),
+ * and shove that data into this single variable.
+ */
+ if (symbol->prev_il_instruction.size() > 0)
+ tmp_prev_il_instruction.candidate_datatypes = symbol->prev_il_instruction[0]->candidate_datatypes;
+ tmp_prev_il_instruction.prev_il_instruction = symbol->prev_il_instruction;
+
+ /* copy the candidate_datatypes list */
+ fake_prev_il_instruction = &tmp_prev_il_instruction;
symbol->il_simple_instruction->datatype = symbol->datatype;
symbol->il_simple_instruction->accept(*this);
- prev_il_instruction = NULL;
+ fake_prev_il_instruction = NULL;
return NULL;
}
@@ -702,7 +751,8 @@
* (or simple_instr_list_c), which iterates backwards.
*/
/* set the desired datatype of the previous il instruction */
- prev_il_instruction->datatype = symbol->datatype;
+ set_datatype_in_prev_il_instructions(symbol->datatype, fake_prev_il_instruction);
+
/* set the datatype for the operand */
il_operand->datatype = symbol->datatype;
il_operand->accept(*this);
@@ -739,8 +789,7 @@
il_operand->datatype = symbol->datatype;
il_operand->accept(*this);
/* set the desired datatype of the previous il instruction */
- prev_il_instruction->datatype = symbol->datatype;
- if (debug) printf("narrow_candidate_datatypes_c::visit(ST_operator_c *symbol) returning. previous_il_instruction->datatype = %p\n", prev_il_instruction->datatype);
+ set_datatype_in_prev_il_instructions(symbol->datatype, fake_prev_il_instruction);
return NULL;
}
@@ -752,7 +801,7 @@
il_operand->datatype = symbol->datatype;
il_operand->accept(*this);
/* set the desired datatype of the previous il instruction */
- prev_il_instruction->datatype = symbol->datatype;
+ set_datatype_in_prev_il_instructions(symbol->datatype, fake_prev_il_instruction);
return NULL;
}
@@ -805,8 +854,7 @@
void *narrow_candidate_datatypes_c::visit(CAL_operator_c *symbol) {
/* set the desired datatype of the previous il instruction */
/* This FB call does not change the value in the current/default IL variable, so we pass the required datatype to the previous IL instruction */
- if (NULL != prev_il_instruction)
- prev_il_instruction->datatype = symbol->datatype;
+ set_datatype_in_prev_il_instructions(symbol->datatype, fake_prev_il_instruction);
return NULL;
}
@@ -827,7 +875,7 @@
if ((NULL != symbol->datatype) && (!is_type(symbol->datatype, bool_type_name_c))) ERROR;
/* set the required datatype of the previous IL instruction, i.e. a bool_type_name_c! */
- if (NULL != prev_il_instruction) prev_il_instruction->datatype = symbol->datatype;
+ set_datatype_in_prev_il_instructions(symbol->datatype, fake_prev_il_instruction);
return NULL;
}
@@ -846,8 +894,7 @@
* However, since that class has not yet been completely finished, we do not yet check this assertion!
*/
// if (NULL != symbol->datatype) ERROR;
- if (NULL != prev_il_instruction)
- prev_il_instruction->datatype = symbol->datatype;
+ set_datatype_in_prev_il_instructions(symbol->datatype, fake_prev_il_instruction);
return NULL;
}
@@ -861,8 +908,7 @@
* However, since that class has not yet been completely finished, we do not yet check this assertion!
*/
// if (NULL != symbol->datatype) ERROR;
- if (NULL != prev_il_instruction)
- prev_il_instruction->datatype = symbol->datatype;
+ set_datatype_in_prev_il_instructions(symbol->datatype, fake_prev_il_instruction);
return NULL;
}
--- a/stage3/narrow_candidate_datatypes.hh Thu Mar 01 10:28:27 2012 +0000
+++ b/stage3/narrow_candidate_datatypes.hh Fri Mar 02 12:53:41 2012 +0000
@@ -42,7 +42,9 @@
search_varfb_instance_type_c *search_varfb_instance_type;
search_base_type_c search_base_type;
symbol_c *il_operand;
- symbol_c *prev_il_instruction;
+ il_instruction_c *fake_prev_il_instruction;
+ std::vector <symbol_c *> *prev_il_instructions;
+ std::vector <symbol_c *> *prev_il_instructions_intersected_datatypes;
bool is_widening_compatible(symbol_c *left_type, symbol_c *right_type, symbol_c *result_type, const struct widen_entry widen_table[]);
--- a/stage3/print_datatypes_error.cc Thu Mar 01 10:28:27 2012 +0000
+++ b/stage3/print_datatypes_error.cc Fri Mar 02 12:53:41 2012 +0000
@@ -92,6 +92,27 @@
return error_found;
}
+
+
+
+
+/* Verify if the datatypes of all prev_il_instructions are valid and equal! */
+static bool are_all_datatypes_of_prev_il_instructions_datatypes_equal(il_instruction_c *symbol) {
+ if (NULL == symbol) ERROR;
+ bool res;
+
+ if (symbol->prev_il_instruction.size() > 0)
+ res = is_type_valid(symbol->prev_il_instruction[0]->datatype);
+
+ for (unsigned int i = 1; i < symbol->prev_il_instruction.size(); i++)
+ res &= is_type_equal(symbol->prev_il_instruction[i-1]->datatype, symbol->prev_il_instruction[i]->datatype);
+
+ return res;
+}
+
+
+
+
/* a helper function... */
symbol_c *print_datatypes_error_c::base_type(symbol_c *symbol) {
/* NOTE: symbol == NULL is valid. It will occur when, for e.g., an undefined/undeclared symbolic_variable is used
@@ -239,7 +260,7 @@
return;
}
- if (NULL == prev_il_instruction) {
+ if (fake_prev_il_instruction->prev_il_instruction.empty()) {
STAGE3_ERROR(0, il_operator, il_operand, "FB invocation operator '%s' must be preceded by a 'LD' (or equivalent) operator.", param_name);
return;
}
@@ -257,7 +278,7 @@
STAGE3_ERROR(0, il_operator, il_operand, "FB called by '%s' operator does not have a parameter named '%s'", param_name, param_name);
return;
}
- if (NULL == prev_il_instruction->datatype) {
+ if (!are_all_datatypes_of_prev_il_instructions_datatypes_equal(fake_prev_il_instruction)) {
STAGE3_ERROR(0, il_operator, il_operand, "Data type incompatibility between parameter '%s' and value being passed.", param_name);
return;
}
@@ -618,12 +639,29 @@
// SYM_REF2(il_instruction_c, label, il_instruction)
void *print_datatypes_error_c::visit(il_instruction_c *symbol) {
if (NULL != symbol->il_instruction) {
- if (symbol->prev_il_instruction.size() > 1) ERROR; /* This assertion is only valid for now. Remove it once flow_control_analysis_c is complete */
- if (symbol->prev_il_instruction.size() == 0) prev_il_instruction = NULL;
- else prev_il_instruction = symbol->prev_il_instruction[0];
-
+// #if 0
+ il_instruction_c tmp_prev_il_instruction(NULL, NULL);
+ /* the narrow algorithm will need access to the intersected candidate_datatype lists of all prev_il_instructions, as well as the
+ * list of the prev_il_instructions.
+ * Instead of creating two 'global' (within the class) variables, we create a single il_instruction_c variable (fake_prev_il_instruction),
+ * and shove that data into this single variable.
+ */
+ tmp_prev_il_instruction.prev_il_instruction = symbol->prev_il_instruction;
+ intersect_prev_candidate_datatype_lists(&tmp_prev_il_instruction);
+ if (are_all_datatypes_of_prev_il_instructions_datatypes_equal(symbol))
+ if (symbol->prev_il_instruction.size() > 0)
+ tmp_prev_il_instruction.datatype = (symbol->prev_il_instruction[0])->datatype;
+ /* Tell the il_instruction the datatype that it must generate - this was chosen by the next il_instruction (remember: we are iterating backwards!) */
+ fake_prev_il_instruction = &tmp_prev_il_instruction;
symbol->il_instruction->accept(*this);
- prev_il_instruction = NULL;
+ fake_prev_il_instruction = NULL;
+// #endif
+// if (symbol->prev_il_instruction.size() > 1) ERROR; /* only valid for now! */
+// if (symbol->prev_il_instruction.size() == 0) prev_il_instruction = NULL;
+// else prev_il_instruction = symbol->prev_il_instruction[0];
+
+// symbol->il_instruction->accept(*this);
+// prev_il_instruction = NULL;
}
return NULL;
@@ -657,7 +695,7 @@
if (NULL == symbol->il_operand_list) symbol->il_operand_list = new il_operand_list_c;
if (NULL == symbol->il_operand_list) ERROR;
- ((list_c *)symbol->il_operand_list)->insert_element(prev_il_instruction, 0);
+ ((list_c *)symbol->il_operand_list)->insert_element(fake_prev_il_instruction, 0);
generic_function_call_t fcall_param = {
/* fcall_param.function_name = */ symbol->function_name,
@@ -671,16 +709,10 @@
/* TODO: check what error message (if any) the compiler will give out if this function invocation
* is not preceded by a LD operator (or another equivalent operator or list of operators).
- * I.e. if it is preceded by an operator or operator list that will set the 'current value'.
- * I.e. if the prev_il_operand == NULL;
*/
handle_function_invocation(symbol, fcall_param);
- /* The first parameter of a non formal function call in IL will be the 'current value' (i.e. the prev_il_instruction)
- * In order to be able to handle this without coding special cases, we simply prepend that symbol
- * to the il_operand_list. This was done in fill_candidate_datatypes_c.
- * We now undo those changes!
- */
+ /* We now undo those changes to the abstract syntax tree made above! */
((list_c *)symbol->il_operand_list)->remove_element(0);
if (((list_c *)symbol->il_operand_list)->n == 0) {
/* if the list becomes empty, then that means that it did not exist before we made these changes, so we delete it! */
@@ -696,9 +728,9 @@
// SYM_REF3(il_expression_c, il_expr_operator, il_operand, simple_instr_list);
void *print_datatypes_error_c::visit(il_expression_c *symbol) {
/* first give the parenthesised IL list a chance to print errors */
- symbol_c *save_prev_il_instruction = prev_il_instruction;
+ il_instruction_c *save_fake_prev_il_instruction = fake_prev_il_instruction;
symbol->simple_instr_list->accept(*this);
- prev_il_instruction = save_prev_il_instruction;
+ fake_prev_il_instruction = save_fake_prev_il_instruction;
/* Now handle the operation (il_expr_operator) that will use the result coming from the parenthesised IL list (i.e. simple_instr_list) */
il_operand = symbol->simple_instr_list; /* This is not a bug! The parenthesised expression will be used as the operator! */
@@ -759,13 +791,31 @@
// SYM_REF1(il_simple_instruction_c, il_simple_instruction, symbol_c *prev_il_instruction;)
void *print_datatypes_error_c::visit(il_simple_instruction_c *symbol) {
- if (symbol->prev_il_instruction.size() > 1) ERROR; /* This assertion is only valid for now. Remove it once flow_control_analysis_c is complete */
- if (symbol->prev_il_instruction.size() == 0) prev_il_instruction = NULL;
- else prev_il_instruction = symbol->prev_il_instruction[0];
-
+ if (symbol->prev_il_instruction.size() > 1) ERROR; /* There should be no labeled insructions inside an IL expression! */
+
+ il_instruction_c tmp_prev_il_instruction(NULL, NULL);
+ /* the print error algorithm will need access to the intersected candidate_datatype lists of all prev_il_instructions, as well as the
+ * list of the prev_il_instructions.
+ * Instead of creating two 'global' (within the class) variables, we create a single il_instruction_c variable (fake_prev_il_instruction),
+ * and shove that data into this single variable.
+ */
+ if (symbol->prev_il_instruction.size() > 0)
+ tmp_prev_il_instruction.candidate_datatypes = symbol->prev_il_instruction[0]->candidate_datatypes;
+ tmp_prev_il_instruction.prev_il_instruction = symbol->prev_il_instruction;
+
+ /* copy the candidate_datatypes list */
+ fake_prev_il_instruction = &tmp_prev_il_instruction;
symbol->il_simple_instruction->accept(*this);
- prev_il_instruction = NULL;
+ fake_prev_il_instruction = NULL;
return NULL;
+
+
+// if (symbol->prev_il_instruction.size() == 0) prev_il_instruction = NULL;
+// else prev_il_instruction = symbol->prev_il_instruction[0];
+
+// symbol->il_simple_instruction->accept(*this);
+// prev_il_instruction = NULL;
+// return NULL;
}
--- a/stage3/print_datatypes_error.hh Thu Mar 01 10:28:27 2012 +0000
+++ b/stage3/print_datatypes_error.hh Fri Mar 02 12:53:41 2012 +0000
@@ -77,8 +77,12 @@
bool warning_found;
/* the current data type of the data stored in the IL stack, i.e. the default variable */
- symbol_c *prev_il_instruction;
- /* the current IL operand being analyzed - its symbol and its data type */
+ il_instruction_c *fake_prev_il_instruction;
+ /* the narrow algorithm will need access to the intersected candidate_datatype lists of all prev_il_instructions, as well as the
+ * list of the prev_il_instructions.
+ * Instead of creating two 'global' (within the class) variables, we create a single il_instruction_c variable (fake_prev_il_instruction),
+ * and shove that data into this single variable.
+ */
symbol_c *il_operand_type;
symbol_c *il_operand;
--- a/stage4/generate_iec/generate_iec.cc Thu Mar 01 10:28:27 2012 +0000
+++ b/stage4/generate_iec/generate_iec.cc Fri Mar 02 12:53:41 2012 +0000
@@ -58,6 +58,10 @@
+#define ERROR error_exit(__FILE__,__LINE__)
+/* function defined in main.cc */
+extern void error_exit(const char *file_name, int line_no);
+
@@ -153,6 +157,13 @@
#endif
+/* A class used to identify an entry (literal, variable, etc...) in the abstract syntax tree with an invalid data type */
+/* This is only used from stage3 onwards. Stages 1 and 2 will never create any instances of invalid_type_name_c */
+// SYM_REF0(invalid_type_name_c)
+void *visit(invalid_type_name_c *symbol) {
+ ERROR;
+ return NULL;
+}
/******************/