diff -r 566414d7ba1f -r 477393b00f95 stage4/generate_c/generate_c_base.cc --- a/stage4/generate_c/generate_c_base.cc Sat Oct 25 13:20:10 2014 +0100 +++ b/stage4/generate_c/generate_c_base.cc Sun Nov 16 12:54:10 2014 +0000 @@ -26,6 +26,30 @@ +/* This file cotains two main classes: + * - generate_c_base_c + * - generate_c_base_and_typeid_c + * + * generate_c_base_c + * ----------------- + * This class generates C code for all literals and varables. In short, all the basic stuff + * that will probably be needed in all other code generating classes. + * It does not however handle derived datatypes. + * + * generate_c_base_and_typeid_c + * ---------------------------- + * This is similar to the generate_c_base_c (from which it inherits), but it also handles + * all the derived datatypes. Note that it does not generate C code for the declaration of + * those datatypes (that is what generate_c_typedecl_c is for), but rather it merely + * generates the name/id of a derived datatype. + * Note too that not all derived datatypes in the IEC 61131-3 have a name (for example, + * VAR a: ARRAY [3..5] of INT END_VAR), in which case an alias for this datatype should + * have been previously generated by either generate_c_typedecl_c or generate_implicit_typedecl_c. + */ + + + + typedef struct { @@ -61,6 +85,12 @@ param_list.clear(); +/* generate_c_base_c + * ----------------- + * This class generates C code for all literals and varables. In short, all the basic stuff + * that will probably be needed in all other code generating classes. + * It does not however handle derived datatypes. + */ class generate_c_base_c: public iterator_visitor_c { protected: @@ -298,6 +328,10 @@ /* B 1.1 - Letters, digits and identifiers */ /*******************************************/ void *visit(identifier_c *symbol) {return print_token(symbol);} + /* If you need the derived_datatype_identifier_c visitor, then you should probably be + * inheriting from generate_c_base_and_typeid_c and not generate_c_base_c !! + */ + void *visit(derived_datatype_identifier_c *symbol) {ERROR; return NULL;} /*********************/ /* B 1.2 - Constants */ @@ -594,12 +628,11 @@ /* Currently only used in REF_TO ANY, which is mapped onto (void *) */ void *visit(generic_type_any_c *symbol) {s4o.print("void"); return NULL;} + /********************************/ /* B 1.3.3 - Derived data types */ /********************************/ - /* leave for derived classes... */ - - + /* enumerated_type_name '#' identifier */ void *visit(enumerated_value_c *symbol) { if (NULL == symbol->datatype) { @@ -619,97 +652,6 @@ } -/* identifier ':' array_spec_init */ -void *visit(array_type_declaration_c *symbol) {ERROR;/* Should never get called! */ return NULL;} - -/* array_specification [ASSIGN array_initialization] */ -/* array_initialization may be NULL ! */ -void *visit(array_spec_init_c *symbol) { - int implicit_id_count = symbol->anotations_map.count("generate_c_annotaton__implicit_type_id"); - if (implicit_id_count != 1) ERROR; - /* this is part of an implicitly declared datatype (i.e. inside a variable decaration), for which an equivalent C datatype - * has already been defined. So, we simly print out the id of that C datatpe... - */ - return symbol->anotations_map["generate_c_annotaton__implicit_type_id"]->accept(*this); -} - -/* ARRAY '[' array_subrange_list ']' OF non_generic_type_name */ -void *visit(array_specification_c *symbol) { - int implicit_id_count = symbol->anotations_map.count("generate_c_annotaton__implicit_type_id"); - if (implicit_id_count != 1) ERROR; - /* this is part of an implicitly declared datatype (i.e. inside a variable decaration), for which an equivalent C datatype - * has already been defined. So, we simly print out the id of that C datatpe... - */ - return symbol->anotations_map["generate_c_annotaton__implicit_type_id"]->accept(*this); -} - - -/* ref_spec: REF_TO (non_generic_type_name | function_block_type_name) */ -void *visit(ref_spec_c *symbol) { - int implicit_id_count = symbol->anotations_map.count("generate_c_annotaton__implicit_type_id"); - if (implicit_id_count != 1) ERROR; - /* this is part of an implicitly declared datatype (i.e. inside a variable decaration), for which an equivalent C datatype - * has already been defined. So, we simly print out the id of that C datatpe... - */ - return symbol->anotations_map["generate_c_annotaton__implicit_type_id"]->accept(*this); -} - -/* For the moment, we do not support initialising reference data types */ -/* ref_spec_init: ref_spec [ ASSIGN ref_initialization ] */ -/* NOTE: ref_initialization may be NULL!! */ -// SYM_REF2(ref_spec_init_c, ref_spec, ref_initialization) -void *visit(ref_spec_init_c *symbol) { - int implicit_id_count = symbol->anotations_map.count("generate_c_annotaton__implicit_type_id"); - if (implicit_id_count != 1) ERROR; - /* this is part of an implicitly declared datatype (i.e. inside a variable decaration), for which an equivalent C datatype - * has already been defined. So, we simly print out the id of that C datatpe... - */ - return symbol->anotations_map["generate_c_annotaton__implicit_type_id"]->accept(*this); -} - -/* ref_type_decl: identifier ':' ref_spec_init */ -void *visit(ref_type_decl_c *symbol) {ERROR;/* Should never get called! */ return NULL;} - - - - - -/* NOTE: visit(subrange_spec_init_c *) - * and visit(subrange_specification_c *) - * together simply print out the integer datatype - * on which the subrange is based. - * - * Future code clean-ups should delete these two - * visit mehotds, and make sure whoever calls them - * uses symbol->datatype instead! - */ -/* subrange_specification ASSIGN signed_integer */ -void *visit(subrange_spec_init_c *symbol) { - TRACE("subrange_spec_init_c"); - symbol->subrange_specification->accept(*this); - return NULL; -} - -/* integer_type_name '(' subrange')' */ -void *visit(subrange_specification_c *symbol) { - TRACE("subrange_specification_c"); - symbol->integer_type_name->accept(*this); - return NULL; -} - - -/* NOTE: Why is this here? This visit() method should not be here!! - * TODO: Figure out who is dependent on this method, and move it to its correct location! - */ -/* helper symbol for array_specification */ -/* array_subrange_list ',' subrange */ -void *visit(array_subrange_list_c *symbol) { - TRACE("array_subrange_list_c"); - print_list(symbol); - return NULL; -} - - /*********************/ /* B 1.4 - Variables */ /*********************/ @@ -720,6 +662,7 @@ return NULL; } + /********************************************/ /* B.1.4.1 Directly Represented Variables */ /********************************************/ @@ -730,15 +673,12 @@ } - /*************************************/ /* B.1.4.2 Multi-element Variables */ /*************************************/ -#if 0 /* subscripted_variable '[' subscript_list ']' */ -SYM_REF2(array_variable_c, subscripted_variable, subscript_list) - -#endif +//SYM_REF2(array_variable_c, subscripted_variable, subscript_list) + /* record_variable '.' field_selector */ /* WARNING: input and/or output variables of function blocks @@ -845,10 +785,205 @@ - - - - - - - +/************************************************************************************************/ +/************************************************************************************************/ +/************************************************************************************************/ +/************************************************************************************************/ +/************************************************************************************************/ +/************************************************************************************************/ +/************************************************************************************************/ +/************************************************************************************************/ +/************************************************************************************************/ +/************************************************************************************************/ + + + +/* generate_c_base_and_typeid_c + * ---------------------------- + * This is similar to the generate_c_base_c (from which it inherits), but it also handles + * all the derived datatypes. Note that it does not generate C code for the declaration of + * those datatypes (that is what generate_c_typedecl_c is for), but rather it merely + * generates the name/id of a derived datatype. + * Note too that not all derived datatypes in the IEC 61131-3 have a name (for example, + * VAR a: ARRAY [3..5] of INT END_VAR), in which case an alias for this datatype should + * have been previously generated by either generate_c_typedecl_c or generate_implicit_typedecl_c. + */ +class generate_c_base_and_typeid_c: public generate_c_base_c { + + public: + generate_c_base_and_typeid_c(stage4out_c *s4o_ptr): generate_c_base_c(s4o_ptr) {} + ~generate_c_base_and_typeid_c(void) {} + + +/*************************/ +/* B.1 - Common elements */ +/*************************/ +/*******************************************/ +/* B 1.1 - Letters, digits and identifiers */ +/*******************************************/ + void *visit(derived_datatype_identifier_c *symbol) { + if (get_datatype_info_c::is_array(symbol->datatype)) { + return symbol->datatype->accept(*this); + } + return print_token(symbol); + } + +/*********************/ +/* B 1.2 - Constants */ +/*********************/ +/**********************/ +/* B.1.3 - Data types */ +/**********************/ +/***********************************/ +/* B 1.3.1 - Elementary Data Types */ +/***********************************/ +/********************************/ +/* B.1.3.2 - Generic data types */ +/********************************/ + /* Currently only used in REF_TO ANY, which is mapped onto (void *) */ + void *visit(generic_type_any_c *symbol) {s4o.print("void"); return NULL;} + +/********************************/ +/* B 1.3.3 - Derived data types */ +/********************************/ + +/* subrange_type_name ':' subrange_spec_init */ +void *visit(subrange_type_declaration_c *symbol) {return symbol->subrange_type_name->accept(*this);} + +/* subrange_specification ASSIGN signed_integer */ +void *visit(subrange_spec_init_c *symbol) {return symbol->subrange_specification->accept(*this);} + +/* integer_type_name '(' subrange')' */ +void *visit(subrange_specification_c *symbol) {return symbol->integer_type_name->accept(*this);} + +/* enumerated_type_name ':' enumerated_spec_init */ +void *visit(enumerated_type_declaration_c *symbol) {return symbol->enumerated_type_name->accept(*this);} + +/* enumerated_specification ASSIGN enumerated_value */ +void *visit(enumerated_spec_init_c *symbol) {return symbol->enumerated_specification->accept(*this);} + + +/* enumerated_type_name '#' identifier */ +/* Handled by generate_c_base_c class!! +void *visit(enumerated_value_c *symbol) {} +*/ + +/* identifier ':' array_spec_init */ +void *visit(array_type_declaration_c *symbol) { + int implicit_id_count = symbol->anotations_map.count("generate_c_annotaton__implicit_type_id"); + if (1 != implicit_id_count) ERROR; + return symbol->anotations_map["generate_c_annotaton__implicit_type_id"]->accept(*this); +} + + + +/* array_specification [ASSIGN array_initialization] */ +/* array_initialization may be NULL ! */ +void *visit(array_spec_init_c *symbol) { + int implicit_id_count = symbol->anotations_map.count("generate_c_annotaton__implicit_type_id"); + if (1 == implicit_id_count) return symbol->anotations_map["generate_c_annotaton__implicit_type_id"]->accept(*this); + if (0 == implicit_id_count) return symbol->datatype->accept(*this); + return NULL; +} + +/* ARRAY '[' array_subrange_list ']' OF non_generic_type_name */ +void *visit(array_specification_c *symbol) { + int implicit_id_count = symbol->anotations_map.count("generate_c_annotaton__implicit_type_id"); + if (1 != implicit_id_count) ERROR; + return symbol->anotations_map["generate_c_annotaton__implicit_type_id"]->accept(*this); +} + + + +/* simple_type_name ':' simple_spec_init */ +void *visit(simple_type_declaration_c *symbol) {return symbol->simple_type_name->accept(*this);} + +/* simple_specification [ASSIGN constant] */ +//SYM_REF2(simple_spec_init_c, simple_specification, constant) +// may be NULL +void *visit(simple_spec_init_c *symbol) {return symbol->simple_specification->accept(*this);} + +/* structure_type_name ':' structure_specification */ +//SYM_REF2(structure_type_declaration_c, structure_type_name, structure_specification) +void *visit(structure_type_declaration_c *symbol) {return symbol->structure_type_name->accept(*this);} + +/* structure_type_name ASSIGN structure_initialization */ +/* structure_initialization may be NULL ! */ +//SYM_REF2(initialized_structure_c, structure_type_name, structure_initialization) +void *visit(initialized_structure_c *symbol) {return symbol->structure_type_name->accept(*this);} + + + +/* ref_spec: REF_TO (non_generic_type_name | function_block_type_name) */ +// SYM_REF1(ref_spec_c, type_name) +void *visit(ref_spec_c *symbol) { + int implicit_id_count = symbol->anotations_map.count("generate_c_annotaton__implicit_type_id"); + if (implicit_id_count > 1) ERROR; + if (implicit_id_count == 1) { + /* this is part of an implicitly declared datatype (i.e. inside a variable decaration), for which an equivalent C datatype + * has already been defined. So, we simly print out the id of that C datatpe... + */ + return symbol->anotations_map["generate_c_annotaton__implicit_type_id"]->accept(*this); + } + /* This is NOT part of an implicitly declared datatype (i.e. we are being called from an visit(ref_type_decl_c *), + * through the visit(ref_spec_init_c*)), so we need to simply print out the name of the datatype we reference to. + */ + //debug_c::print(symbol); ERROR; + symbol->type_name->accept(*this); + s4o.print("*"); + return NULL; +} + +/* For the moment, we do not support initialising reference data types */ +/* ref_spec_init: ref_spec [ ASSIGN ref_initialization ] */ +/* NOTE: ref_initialization may be NULL!! */ +// SYM_REF2(ref_spec_init_c, ref_spec, ref_initialization) +void *visit(ref_spec_init_c *symbol) { + /* NOTE An ref_type_decl_c will be created in stage4 for each implicitly defined REF_TO datatype, + * and this generate_c_typedecl_c will be called to define that REF_TO datatype in C. + * However, every implictly defined REF_TO datatype with the exact same parameters will be mapped + * to the same identifier (e.g: __REF_TO_INT). + * In order for the C compiler not to find the same datatype being defined two or more times, + * we will keep track of the datatypes that have already been declared, and henceforth + * only declare the datatypes that have not been previously defined. + */ + int implicit_id_count = symbol->anotations_map.count("generate_c_annotaton__implicit_type_id"); + if (1 < implicit_id_count) ERROR; + if (1 == implicit_id_count) + return symbol->anotations_map["generate_c_annotaton__implicit_type_id"]->accept(*this); + return symbol->ref_spec->accept(*this); // this is probably pointing to an identifier_c !! +} + +/* ref_type_decl: identifier ':' ref_spec_init */ +// SYM_REF2(ref_type_decl_c, ref_type_name, ref_spec_init) +void *visit(ref_type_decl_c *symbol) { + TRACE("ref_type_decl_c"); + /* NOTE An ref_type_decl_c will be created in stage4 for each implicitly defined REF_TO datatype, + * and this generate_c_typedecl_c will be called to define that REF_TO datatype in C. + * However, every implictly defined REF_TO datatype with the exact same parameters will be mapped + * to the same identifier (e.g: __REF_TO_INT). + * In order for the C compiler not to find the same datatype being defined two or more times, + * we will keep track of the datatypes that have already been declared, and henceforth + * only declare the datatypes that have not been previously defined. + */ + int implicit_id_count = symbol->anotations_map.count("generate_c_annotaton__implicit_type_id"); + if (0 != implicit_id_count) ERROR; + //symbol->anotations_map["generate_c_annotaton__implicit_type_id"]->accept(generate_c_base); + return symbol->ref_type_name->accept(*this); +} + + +}; /* class generate_c_base_and_typeid_c */ + + + + + + + + + + + + +