--- a/absyntax_utils/search_varfb_instance_type.cc Wed Feb 01 13:01:08 2012 +0000
+++ b/absyntax_utils/search_varfb_instance_type.cc Wed Feb 01 19:49:11 2012 +0000
@@ -1,7 +1,7 @@
/*
* matiec - a compiler for the programming languages defined in IEC 61131-3
*
- * Copyright (C) 2003-2011 Mario de Sousa (msousa@fe.up.pt)
+ * Copyright (C) 2003-2012 Mario de Sousa (msousa@fe.up.pt)
* Copyright (C) 2007-2011 Laurent Bessard and Edouard Tisserant
*
* This program is free software: you can redistribute it and/or modify
@@ -75,225 +75,134 @@
*
* Member functions:
* ================
+ * get_basetype_id() ---> returns 2A (implemented, although currently it is not needed! )
* get_basetype_decl() ---> returns 2B
* get_type_id() ---> returns 1A
*
- * Since we haven't yet needed them, we don't yet implement
- * get_basetype_id() ----> would return 2A
- * get_type_decl() ----> would return 1B
+ * Since we haven't yet needed it, we don't yet implement
+ * get_type_decl() ---> returns 1B
*/
-/*
- * TODO: this code has a memory leak...
- * We call 'new' in several locations, but bever get to 'delete' the object instances...
- */
+
#include "absyntax_utils.hh"
+void search_varfb_instance_type_c::init(void) {
+ this->current_type_id = NULL;
+ this->current_basetype_id = NULL;
+ this->current_basetype_decl = NULL;
+ this->current_field_selector = NULL;
+ this->is_complex = false;
+}
+
+
search_varfb_instance_type_c::search_varfb_instance_type_c(symbol_c *search_scope): search_var_instance_decl(search_scope) {
- this->decompose_var_instance_name = NULL;
- this->current_structelement_name = NULL;
- this->current_typeid = NULL;
- this->current_basetypeid = NULL;
-}
-
-symbol_c *search_varfb_instance_type_c::get_type_decl(symbol_c *variable_name) {
- this->current_structelement_name = NULL;
- this->current_typeid = NULL;
- this->current_basetypeid = NULL;
- this->decompose_var_instance_name = new decompose_var_instance_name_c(variable_name);
- if (NULL == decompose_var_instance_name) ERROR;
-
- /* find the part of the variable name that will appear in the
- * variable declaration, for e.g., in window.point.x, this would be
- * window!
- */
- symbol_c *var_name_part = decompose_var_instance_name->next_part();
- if (NULL == var_name_part) ERROR;
-
- /* Now we try to find the variable instance declaration, to determine its type... */
- symbol_c *var_decl = search_var_instance_decl.get_decl(var_name_part);
- if (NULL == var_decl) ERROR;
-
- /* if it is a struct or function block, we must search the type
- * of the struct or function block member.
- * This is done by this class visiting the var_decl.
- * This class, while visiting, will recursively call
- * decompose_var_instance_name->get_next() when and if required...
- */
- symbol_c *res = (symbol_c *)var_decl->accept(*this);
- /* NOTE: A Null result is not really an internal compiler error, but rather an error in
- * the IEC 61131-3 source code being compiled. This means we cannot just abort the compiler with ERROR.
- * // if (NULL == res) ERROR;
- */
- if (NULL == res) return NULL;
-
- /* make sure that we have decomposed all structure elements of the variable name */
- symbol_c *var_name = decompose_var_instance_name->next_part();
- /* NOTE: A non-NULL result is not really an internal compiler error, but rather an error in
- * the IEC 61131-3 source code being compiled.
- * (for example, 'int_var.struct_elem' in the source code, when 'int_var' is a simple integer,
- * and not a structure, will result in this result being non-NULL!)
- * This means we cannot just abort the compiler with ERROR.
- * // if (NULL != var_name) ERROR;
- */
- if (NULL != var_name) return NULL;
-
- return res;
+ this->init();
+}
+
+
+/* We expect to be passed a symbolic_variable_c */
+symbol_c *search_varfb_instance_type_c::get_type_id(symbol_c *variable_name) {
+ this->init();
+ variable_name->accept(*this);
+ return current_type_id;
+}
+
+
+symbol_c *search_varfb_instance_type_c::get_basetype_id(symbol_c *variable_name) {
+ this->init();
+ variable_name->accept(*this);
+ return current_basetype_id;
}
symbol_c *search_varfb_instance_type_c::get_basetype_decl(symbol_c *variable_name) {
- symbol_c *res = get_type_decl(variable_name);
- if (NULL == res) return NULL;
- return (symbol_c *)base_type(res);
+ this->init();
+ variable_name->accept(*this);
+ return current_basetype_decl;
}
+
+
+
unsigned int search_varfb_instance_type_c::get_vartype(symbol_c *variable_name) {
- this->current_structelement_name = NULL;
- this->current_typeid = NULL;
- this->current_basetypeid = NULL;
- this->is_complex = false;
- this->decompose_var_instance_name = new decompose_var_instance_name_c(variable_name);
- if (NULL == decompose_var_instance_name) ERROR;
-
- /* find the part of the variable name that will appear in the
- * variable declaration, for e.g., in window.point.x, this would be
- * window!
- */
- symbol_c *var_name_part = decompose_var_instance_name->next_part();
- if (NULL == var_name_part) ERROR;
-
- /* Now we try to find the variable instance declaration, to determine its type... */
- symbol_c *var_decl = search_var_instance_decl.get_decl(var_name_part);
- if (NULL == var_decl) {
- /* variable instance declaration not found! */
- return 0;
- }
-
- /* if it is a struct or function block, we must search the type
- * of the struct or function block member.
- * This is done by this class visiting the var_decl.
- * This class, while visiting, will recursively call
- * decompose_var_instance_name->get_next() when and if required...
- */
- var_decl->accept(*this);
- unsigned int res = search_var_instance_decl.get_vartype();
-
- /* make sure that we have decomposed all structure elements of the variable name */
- symbol_c *var_name = decompose_var_instance_name->next_part();
- if (NULL != var_name) ERROR;
-
- return res;
-}
-
-symbol_c *search_varfb_instance_type_c::get_type_id(symbol_c *variable_name) {
- this->current_typeid = NULL;
- symbol_c *vartype = this->get_type_decl(variable_name);
- if (this->current_typeid != NULL)
- return this->current_typeid;
- else
- return vartype;
-}
+ this->init();
+ return search_var_instance_decl.get_vartype(variable_name);
+}
+
+
bool search_varfb_instance_type_c::type_is_complex(void) {
return this->is_complex;
}
-/* a helper function... */
-void *search_varfb_instance_type_c::visit_list(list_c *list) {
- if (NULL == current_structelement_name) ERROR;
-
- for(int i = 0; i < list->n; i++) {
- void *res = list->elements[i]->accept(*this);
- if (res != NULL)
- return res;
- }
- /* not found! */
- return NULL;
-}
-
-/* a helper function... */
-void *search_varfb_instance_type_c::base_type(symbol_c *symbol) {
- search_base_type_c search_base_type;
- return symbol->accept(search_base_type);
-}
-
-/* We override the base class' visitor to identifier_c.
- * This is so because the base class does not consider a function block
- * to be a type, unlike this class that allows a variable instance
- * of a function block type...
- */
-void *search_varfb_instance_type_c::visit(identifier_c *type_name) {
- /* we only store the new type id if none had been found yet.
- * Since we will recursively carry on looking at the base type
- * to determine the base type declaration and id, we must only set this variable
- * the first time.
- * e.g. TYPE myint1_t : int := 1;
- * myint2_t : int1_t := 2;
- * myint3_t : int2_t := 3;
- * END_TYPE;
- * VAR
- * myint1 : myint1_t;
- * myint2 : myint2_t;
- * myint3 : myint3_t;
- * END_VAR
- *
- * If we ask for typeid of myint3, it must return myint3_t
- * If we ask for basetypeid of myint3, it must return int
- *
- * When determining the data type of myint3, we will recursively go all the way
- * down to int, but we must still only store myint3_t as the base type id.
- */
- if (NULL == this->current_typeid)
- this->current_typeid = type_name;
- this->current_basetypeid = type_name;
-
- /* look up the type declaration... */
- symbol_c *fb_decl = function_block_type_symtable.find_value(type_name);
- if (fb_decl != function_block_type_symtable.end_value())
- /* Type declaration found!! */
- return fb_decl->accept(*this);
-
- /* No. It is not a function block, so we let
- * the base class take care of it...
- */
- return search_base_type_c::visit(type_name);
-}
+
+
+
+
+
+
+
+
/********************************/
/* B 1.3.3 - Derived data types */
/********************************/
-
/* identifier ':' array_spec_init */
+/* NOTE: I don't think this will ever get called, since in the visit method for array_variable_c
+ * we use the basetype_decl for recursively calling this class, and the base type should never be a
+ * array_type_declaration_c, but for now, let's leave it in...
+ */
void *search_varfb_instance_type_c::visit(array_type_declaration_c *symbol) {
- return symbol->array_spec_init->accept(*this);
+ ERROR;
+ return NULL;
}
/* array_specification [ASSIGN array_initialization] */
/* array_initialization may be NULL ! */
+/* NOTE: I don't think this will ever get called, since in the visit method for array_variable_c
+ * we use the basetype_decl for recursively calling this class, and the base type should never be a
+ * array_spec_init_c, but for now, let's leave it in...
+ */
void *search_varfb_instance_type_c::visit(array_spec_init_c *symbol) {
- return symbol->array_specification->accept(*this);
+ /* Note that the 'array_specification' may be either an identifier of a previsously defined array type,
+ * or an array_specification_c, so we can not stop here and simply return a array_spec_init_c,
+ * especially if we are looking for the base class!
+ */
+ ERROR;
+ return NULL;
}
/* ARRAY '[' array_subrange_list ']' OF non_generic_type_name */
+/* NOTE: This method will be reached after being called from the
+ * search_varfb_instance_type_c::visit(array_variable_c *symbol)
+ * method, so we must return the data type of the data stored in the array,
+ * and not the data type of the array itself!
+ */
void *search_varfb_instance_type_c::visit(array_specification_c *symbol) {
- this->is_complex = true;
- this->current_typeid = symbol;
- return symbol->non_generic_type_name->accept(*this);
-}
+ /* found the type of the element we were looking for! */
+ current_type_id = symbol->non_generic_type_name;
+ current_basetype_decl = search_base_type.get_basetype_decl(current_type_id);
+ current_basetype_id = search_base_type.get_basetype_id (current_type_id);
+
+ return NULL;
+}
+
/* structure_type_name ':' structure_specification */
/* NOTE: this is only used inside a TYPE ... END_TYPE declaration.
* It is never used directly when declaring a new variable!
*/
+/* NOTE: I don't think this will ever get called, since in the visit method for structured_variable_c
+ * we use the basetype_decl for recursively calling this class, and the base type should never be a
+ * structure_type_declaration_c, but for now, let's leave it in...
+ */
void *search_varfb_instance_type_c::visit(structure_type_declaration_c *symbol) {
- this->is_complex = true;
-
- if (NULL == current_structelement_name) ERROR;
- return symbol->structure_specification->accept(*this);
+ if (NULL == current_field_selector) ERROR;
+ symbol->structure_specification->accept(*this);
+ return NULL;
/* NOTE: structure_specification will point to either a
* initialized_structure_c
* OR A
@@ -304,51 +213,42 @@
/* structure_type_name ASSIGN structure_initialization */
/* structure_initialization may be NULL ! */
// SYM_REF2(initialized_structure_c, structure_type_name, structure_initialization)
-/* NOTE: only the initialized structure is ever used when declaring a new variable instance */
+/* NOTE: only the initialized structure is never used when declaring a new variable instance */
+/* NOTE: I don't think this will ever get called, since in the visit method for structured_variable_c
+ * we use the basetype_decl for recursively calling this class, and the base type should never be a
+ * initialized_structure_c, but for now, let's leave it in...
+ */
void *search_varfb_instance_type_c::visit(initialized_structure_c *symbol) {
- this->is_complex = true;
- if (NULL != current_structelement_name) ERROR;
-
- /* make sure that we have decomposed all structure elements of the variable name */
- symbol_c *var_name = decompose_var_instance_name->next_part();
- if (NULL == var_name) {
- /* this is it... !
- * No need to look any further...
- * Note also that, unlike for the struct types, a function block may
- * not be defined based on another (i.e. no inheritance is allowed),
- * so this function block is already the most base type.
- * We simply return it.
- */
- return (void *)symbol;
- }
-
- /* reset current_type_id because of new structure element part */
- this->current_typeid = NULL;
-
- /* look for the var_name in the structure declaration */
- current_structelement_name = var_name;
-
- /* recursively find out the data type of current_structelement_name... */
- return symbol->structure_type_name->accept(*this);
+ if (NULL != current_field_selector) ERROR;
+
+ /* recursively find out the data type of current_field_selector... */
+ symbol->structure_type_name->accept(*this);
+ return NULL;
}
/* helper symbol for structure_declaration */
/* structure_declaration: STRUCT structure_element_declaration_list END_STRUCT */
/* structure_element_declaration_list structure_element_declaration ';' */
void *search_varfb_instance_type_c::visit(structure_element_declaration_list_c *symbol) {
- if (NULL == current_structelement_name) ERROR;
+ if (NULL == current_field_selector) ERROR;
+
/* now search the structure declaration */
- return visit_list(symbol);
+ for(int i = 0; i < symbol->n; i++) {
+ symbol->elements[i]->accept(*this);
+ }
+
+ return NULL;
}
/* structure_element_name ':' spec_init */
void *search_varfb_instance_type_c::visit(structure_element_declaration_c *symbol) {
- if (NULL == current_structelement_name) ERROR;
-
- if (compare_identifiers(symbol->structure_element_name, current_structelement_name) == 0) {
- current_structelement_name = NULL;
+ if (NULL == current_field_selector) ERROR;
+
+ if (compare_identifiers(symbol->structure_element_name, current_field_selector) == 0) {
/* found the type of the element we were looking for! */
- return symbol->spec_init->accept(*this);
+ current_type_id = symbol->spec_init;
+ current_basetype_decl = search_base_type.get_basetype_decl(current_type_id);
+ current_basetype_id = search_base_type.get_basetype_id (current_type_id);
}
/* Did not find the type of the element we were looking for! */
@@ -364,6 +264,79 @@
void *search_varfb_instance_type_c::visit(structure_element_initialization_c *symbol) {ERROR; return NULL;} /* should never get called... */
+/*********************/
+/* B 1.4 - Variables */
+/*********************/
+// SYM_REF1(symbolic_variable_c, var_name)
+void *search_varfb_instance_type_c::visit(symbolic_variable_c *symbol) {
+ /* Note: although the method is called get_decl(), it is getting the declaration of the variable, which for us is the type_id of that variable! */
+ current_type_id = search_var_instance_decl.get_decl (symbol->var_name);
+ current_basetype_decl = search_base_type.get_basetype_decl(current_type_id);
+ current_basetype_id = search_base_type.get_basetype_id (current_type_id);
+
+ if (NULL == current_type_id) ERROR; /* why should this be an error? what if the variable has not been declared? */
+
+ return NULL;
+}
+
+/********************************************/
+/* B.1.4.1 Directly Represented Variables */
+/********************************************/
+// SYM_TOKEN(direct_variable_c)
+/* We do not yet handle this. Will we ever need to handle it, as the data type of the direct variable is
+ * directly obtainable from the syntax of the direct variable itself?
+ */
+
+/*************************************/
+/* B 1.4.2 - Multi-element variables */
+/*************************************/
+/* subscripted_variable '[' subscript_list ']' */
+// SYM_REF2(array_variable_c, subscripted_variable, subscript_list)
+/* NOTE: when passed a array_variable_c, which represents some IEC61131-3 code similar to X[42]
+ * we must return the data type of the value _stored_ in the array.
+ * If you want to get the data type of the array itself (i.e. just the X variable, without the [42])
+ * then this class must be called with the identifier_c 'X'.
+ */
+void *search_varfb_instance_type_c::visit(array_variable_c *symbol) {
+ this->is_complex = true;
+
+ /* determine the data type of the subscripted_variable...
+ * This should be an array_specification_c
+ * ARRAY [xx..yy] OF Stored_Data_Type
+ */
+ symbol->subscripted_variable->accept(*this);
+
+ /* Now we determine the 'Stored_Data_Type', i.e. the data type of the variable stored in the array. */
+ if (NULL != current_basetype_decl) {
+ current_basetype_decl->accept(*this);
+ }
+
+ return NULL;
+}
+
+
+/* record_variable '.' field_selector */
+/* WARNING: input and/or output variables of function blocks
+ * may be accessed as fields of a structured variable!
+ * Code handling a structured_variable_c must take
+ * this into account!
+ */
+// SYM_REF2(structured_variable_c, record_variable, field_selector)
+void *search_varfb_instance_type_c::visit(structured_variable_c *symbol) {
+ this->is_complex = true;
+ symbol->record_variable->accept(*this);
+
+ /* Now we search for the data type of the field... But only if we were able to determine the data type of the variable */
+ if (NULL != current_basetype_decl) {
+ current_field_selector = symbol->field_selector;
+ current_basetype_decl->accept(*this);
+ current_field_selector = NULL;
+ }
+
+ return NULL;
+}
+
+
/**************************************/
/* B.1.5 - Program organization units */
@@ -371,46 +344,18 @@
/*****************************/
/* B 1.5.2 - Function Blocks */
/*****************************/
+
/* FUNCTION_BLOCK derived_function_block_name io_OR_other_var_declarations function_block_body END_FUNCTION_BLOCK */
// SYM_REF4(function_block_declaration_c, fblock_name, var_declarations, fblock_body, unused)
void *search_varfb_instance_type_c::visit(function_block_declaration_c *symbol) {
- /* make sure that we have decomposed all structure elements of the variable name */
- symbol_c *var_name = decompose_var_instance_name->next_part();
- if (NULL == var_name) {
- /* this is it... !
- * No need to look any further...
- * Note also that, unlike for the struct types, a function block may
- * not be defined based on another (i.e. no inheritance is allowed),
- * so this function block is already the most base type.
- * We simply return it.
- */
- return (void *)symbol;
- }
-
- /* reset current_type_id because of new structure element part */
- this->current_typeid = NULL;
-
- /* now search the function block declaration for the variable... */
- search_var_instance_decl_c search_decl(symbol);
- symbol_c *var_decl = search_decl.get_decl(var_name);
- if (NULL == var_decl) {
- /* variable instance declaration not found! */
- return NULL;
- }
-#if 0
- /* We have found the declaration.
- * Should we look any further?
- */
- var_name = decompose_var_instance_name->next_part();
- if (NULL == var_name) {
- /* this is it... ! */
- return base_type(var_decl);
- }
-
- current_structelement_name = var_name;
- /* recursively find out the data type of var_name... */
- return symbol->var_declarations->accept(*this);
-#endif
- /* carry on recursively, in case the variable has more elements to be decomposed... */
- return var_decl->accept(*this);
-}
+ if (NULL == current_field_selector) ERROR;
+
+ /* now search the function block declaration for the variable... */
+ /* If not found, these pointers will all be set to NULL!! */
+ search_var_instance_decl_c search_decl(symbol);
+ current_type_id = search_decl.get_decl(current_field_selector);
+ current_basetype_decl = search_base_type.get_basetype_decl(current_type_id);
+ current_basetype_id = search_base_type.get_basetype_id (current_type_id);
+
+ return NULL;
+}