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