Add limited support for the REF() operator (defined in v3 of IEC 61131-3)
authormjsousa
Sun, 02 Mar 2014 16:42:56 +0000
changeset 873 dea39ef02847
parent 872 3d682f87c870
child 874 b8fa360b376d
Add limited support for the REF() operator (defined in v3 of IEC 61131-3)
absyntax/absyntax.def
lib/accessor.h
main.cc
stage1_2/iec_bison.yy
stage1_2/iec_flex.ll
stage1_2/stage1_2.cc
stage1_2/stage1_2.hh
stage1_2/stage1_2_priv.hh
stage3/fill_candidate_datatypes.cc
stage3/fill_candidate_datatypes.hh
stage3/narrow_candidate_datatypes.cc
stage3/narrow_candidate_datatypes.hh
stage3/print_datatypes_error.cc
stage3/print_datatypes_error.hh
stage4/generate_c/generate_c.cc
stage4/generate_c/generate_c_st.cc
stage4/generate_iec/generate_iec.cc
--- a/absyntax/absyntax.def	Mon Feb 24 22:00:55 2014 +0000
+++ b/absyntax/absyntax.def	Sun Mar 02 16:42:56 2014 +0000
@@ -1090,6 +1090,7 @@
 /***********************/
 /* B 3.1 - Expressions */
 /***********************/
+SYM_REF1(ref_expression_c, exp)  /* an extension to the IEC 61131-3 standard - based on the IEC 61131-3 v3 standard. Returns address of the varible! */
 SYM_REF2(or_expression_c, l_exp, r_exp)
 SYM_REF2(xor_expression_c, l_exp, r_exp)
 SYM_REF2(and_expression_c, l_exp, r_exp)
--- a/lib/accessor.h	Mon Feb 24 22:00:55 2014 +0000
+++ b/lib/accessor.h	Sun Mar 02 16:42:56 2014 +0000
@@ -92,6 +92,7 @@
 	__GET_VAR(((*name) __VA_ARGS__))
 #define __GET_LOCATED(name, ...)\
 	((name.flags & __IEC_FORCE_FLAG) ? name.fvalue __VA_ARGS__ : (*(name.value)) __VA_ARGS__)
+
 #define __GET_VAR_BY_REF(name, ...)\
 	((name.flags & __IEC_FORCE_FLAG) ? &(name.fvalue __VA_ARGS__) : &(name.value __VA_ARGS__))
 #define __GET_EXTERNAL_BY_REF(name, ...)\
@@ -101,6 +102,16 @@
 #define __GET_LOCATED_BY_REF(name, ...)\
 	((name.flags & __IEC_FORCE_FLAG) ? &(name.fvalue __VA_ARGS__) : &((*(name.value)) __VA_ARGS__))
 
+#define __GET_VAR_REF(name, ...)\
+	(&(name.value __VA_ARGS__))
+#define __GET_EXTERNAL_REF(name, ...)\
+	(&((*(name.value)) __VA_ARGS__))
+#define __GET_EXTERNAL_FB_REF(name, ...)\
+	(&(__GET_VAR(((*name) __VA_ARGS__))))
+#define __GET_LOCATED_REF(name, ...)\
+	(&((*(name.value)) __VA_ARGS__))
+
+
 // variable setting macros
 #define __SET_VAR(prefix, name, new_value, ...)\
 	if (!(prefix name.flags & __IEC_FORCE_FLAG)) prefix name.value __VA_ARGS__ = new_value
--- a/main.cc	Mon Feb 24 22:00:55 2014 +0000
+++ b/main.cc	Sun Mar 02 16:42:56 2014 +0000
@@ -121,10 +121,11 @@
       /* Version 1.0 is Official Release                    */
       /******************************************************/
   printf("  s : allow use of safe extensions (e.g. SAFExxx data types))\n");
-  printf("  n : allow use of nested comments\n");
+  printf("  n : allow use of nested comments (an IEC 61131-3 v3 feature)\n");
+  printf("  r : allow use of REF() operator  (an IEC 61131-3 v3 feature)\n");
   printf("  c : create conversion functions for enumerated data types\n");
   printf("\n");
-  printf("%s - Copyright (C) 2003-2011 \n"
+  printf("%s - Copyright (C) 2003-2014 \n"
          "This program comes with ABSOLUTELY NO WARRANTY!\n"
          "This is free software licensed under GPL v3, and you are welcome to redistribute it under the conditions specified by this license.\n", PACKAGE_NAME);
 }
@@ -143,12 +144,13 @@
   stage1_2_options.full_token_loc       = false; /* error messages specify full token location */
   stage1_2_options.conversion_functions = false; /* Create a conversion function for derived datatype */
   stage1_2_options.nested_comments      = false; /* Allow the use of nested comments. */
+  stage1_2_options.ref_operator         = false; /* Allow the use of REF() operator. */
   stage1_2_options.includedir           = NULL;  /* Include directory, where included files will be searched for... */
 
   /******************************************/
   /*   Parse command line options...        */
   /******************************************/
-  while ((optres = getopt(argc, argv, ":nhvfscI:T:")) != -1) {
+  while ((optres = getopt(argc, argv, ":nhvfrscI:T:")) != -1) {
     switch(optres) {
     case 'h':
       printusage(argv[0]);
@@ -167,6 +169,10 @@
       stage1_2_options.safe_extensions = true;
       break;
 
+    case 'r':
+      stage1_2_options.ref_operator = true;
+      break;
+
     case 'c':
       stage1_2_options.conversion_functions = true;
       break;
--- a/stage1_2/iec_bison.yy	Mon Feb 24 22:00:55 2014 +0000
+++ b/stage1_2/iec_bison.yy	Sun Mar 02 16:42:56 2014 +0000
@@ -412,6 +412,8 @@
 %type <leaf>	en_identifier
 %type <leaf>	eno_identifier
 
+/* Keyword in IEC 61131-3 v3 */
+%token	REF
 
 
 
@@ -1290,6 +1292,7 @@
  *      are not required. Their values are integrated
  *      directly into other rules...
  */
+%type  <leaf>	ref_expression  /* an extension to the IEC 61131-3 v2 standard, based on the IEC 61131-3 v3 standard */ 
 %type  <leaf>	expression
 %type  <leaf>	xor_expression
 %type  <leaf>	and_expression
@@ -7057,6 +7060,7 @@
 /***********************/
 expression:
   xor_expression
+| ref_expression  /* an extension to the IEC 61131-3 v2 standard, based on the IEC 61131-3 v3 standard */ 
 | expression OR xor_expression
 	{$$ = new or_expression_c($1, $3, locloc(@$));}
 /* ERROR_CHECK_BEGIN */
@@ -7069,6 +7073,14 @@
 /* ERROR_CHECK_END */
 ;
 
+/*  REF(var_name) */
+/*  This is an extension to the IEC 61131-3 standard. It is actually defined in the IEC 61131-3 v3 standard */
+/*  The REF() operator returns the adrress of the variable. Basically, it returns a pointer to the variable */
+ref_expression:
+  REF '(' symbolic_variable ')'
+	{$$ = new ref_expression_c($3, locloc(@$));}
+;
+
 xor_expression:
   and_expression
 | xor_expression XOR and_expression
--- a/stage1_2/iec_flex.ll	Mon Feb 24 22:00:55 2014 +0000
+++ b/stage1_2/iec_flex.ll	Sun Mar 02 16:42:56 2014 +0000
@@ -1245,6 +1245,8 @@
 	/******************************************************/
 
 
+REF	{if (get_opt_ref_operator()) return REF; else unput(0);}		/* Keyword in IEC 61131-3 v3 */
+
 EN	return EN;			/* Keyword */
 ENO	return ENO;			/* Keyword */
 
--- a/stage1_2/stage1_2.cc	Mon Feb 24 22:00:55 2014 +0000
+++ b/stage1_2/stage1_2.cc	Sun Mar 02 16:42:56 2014 +0000
@@ -69,6 +69,13 @@
 bool nested_comments_ = false;
 bool get_opt_nested_comments() {return nested_comments_;}
 
+/************************************/
+/* whether to allow REF() operator  */
+/************************************/
+bool ref_operator_ = false;
+bool get_opt_ref_operator() {return ref_operator_;}
+
+
 /******************************************************/
 /* whether we are supporting conversion functions     */
 /* for enumerate data types                           */
@@ -248,6 +255,7 @@
        */
 
   nested_comments_ = options.nested_comments;    
+  ref_operator_    = options.ref_operator;    
   safe_extensions_ = options.safe_extensions;
   conversion_functions_ = options.conversion_functions;
   return stage2__(filename, options.includedir, tree_root_ref, options.full_token_loc);
--- a/stage1_2/stage1_2.hh	Mon Feb 24 22:00:55 2014 +0000
+++ b/stage1_2/stage1_2.hh	Sun Mar 02 16:42:56 2014 +0000
@@ -60,6 +60,7 @@
 	bool full_token_loc;       /* error messages specify full token location */
 	bool conversion_functions; /* Create a conversion function for derived datatype */
 	bool nested_comments;      /* Allow the use of nested comments. */
+	bool ref_operator;         /* Allow the use of REF() operator. */
 	const char *includedir;    /* Include directory, where included files will be searched for... */
 } stage1_2_options_t;
 
--- a/stage1_2/stage1_2_priv.hh	Mon Feb 24 22:00:55 2014 +0000
+++ b/stage1_2/stage1_2_priv.hh	Sun Mar 02 16:42:56 2014 +0000
@@ -93,6 +93,12 @@
 /************************************/
 bool get_opt_nested_comments();
 
+/************************************/
+/* whether to allow REF() operator  */
+/************************************/
+bool get_opt_ref_operator();
+
+
 
 /*************************************************************/
 /*************************************************************/
--- a/stage3/fill_candidate_datatypes.cc	Mon Feb 24 22:00:55 2014 +0000
+++ b/stage3/fill_candidate_datatypes.cc	Sun Mar 02 16:42:56 2014 +0000
@@ -1832,6 +1832,15 @@
 /***********************/
 /* B 3.1 - Expressions */
 /***********************/
+/* SYM_REF1(ref_expression_c, exp)  --> an extension to the IEC 61131-3 standard - based on the IEC 61131-3 v3 standard. Returns address of the varible! */
+void *fill_candidate_datatypes_c::visit(  ref_expression_c  *symbol) {
+  symbol->exp->accept(*this);
+  /* we should really check whether the expression is merely a variable. For now, leave it for the future! */
+  /* For now, we handle references (i.e. pointers) as ULINT datatypes! */
+  add_datatype_to_candidate_list(symbol, &get_datatype_info_c::ulint_type_name);
+  return NULL;
+}
+    
 void *fill_candidate_datatypes_c::visit(   or_expression_c  *symbol) {return handle_binary_expression  (widen_OR_table,  symbol, symbol->l_exp, symbol->r_exp);}
 void *fill_candidate_datatypes_c::visit(   xor_expression_c *symbol) {return handle_binary_expression  (widen_XOR_table, symbol, symbol->l_exp, symbol->r_exp);}
 void *fill_candidate_datatypes_c::visit(   and_expression_c *symbol) {return handle_binary_expression  (widen_AND_table, symbol, symbol->l_exp, symbol->r_exp);}
--- a/stage3/fill_candidate_datatypes.hh	Mon Feb 24 22:00:55 2014 +0000
+++ b/stage3/fill_candidate_datatypes.hh	Sun Mar 02 16:42:56 2014 +0000
@@ -327,6 +327,7 @@
     /***********************/
     /* B 3.1 - Expressions */
     /***********************/
+    void *visit(ref_expression_c *symbol);
     void *visit(or_expression_c *symbol);
     void *visit(xor_expression_c *symbol);
     void *visit(and_expression_c *symbol);
--- a/stage3/narrow_candidate_datatypes.cc	Mon Feb 24 22:00:55 2014 +0000
+++ b/stage3/narrow_candidate_datatypes.cc	Sun Mar 02 16:42:56 2014 +0000
@@ -1337,6 +1337,17 @@
 /***********************/
 /* B 3.1 - Expressions */
 /***********************/
+/* SYM_REF1(ref_expression_c, exp)  --> an extension to the IEC 61131-3 standard - based on the IEC 61131-3 v3 standard. Returns address of the varible! */
+void *narrow_candidate_datatypes_c::visit(  ref_expression_c  *symbol) {
+  if (symbol->exp->candidate_datatypes.size() > 0) {
+    symbol->exp->datatype = symbol->exp->candidate_datatypes[0]; /* just use the first possible datatype */
+    symbol->exp->accept(*this);
+  }
+  return NULL;
+}
+
+
+
 /* allow_enums is FALSE by default!!
  * deprecated_operation is NULL by default!!
  * if (allow_enums) then consider that we are ectually processing an equ_expression or notequ_expression, where two enums of the same data type may also be legally compared 
--- a/stage3/narrow_candidate_datatypes.hh	Mon Feb 24 22:00:55 2014 +0000
+++ b/stage3/narrow_candidate_datatypes.hh	Sun Mar 02 16:42:56 2014 +0000
@@ -303,6 +303,7 @@
     /***********************/
     /* B 3.1 - Expressions */
     /***********************/
+    void *visit(ref_expression_c *symbol);
     void *visit(or_expression_c *symbol);
     void *visit(xor_expression_c *symbol);
     void *visit(and_expression_c *symbol);
--- a/stage3/print_datatypes_error.cc	Mon Feb 24 22:00:55 2014 +0000
+++ b/stage3/print_datatypes_error.cc	Sun Mar 02 16:42:56 2014 +0000
@@ -1032,6 +1032,15 @@
 /***********************/
 /* B 3.1 - Expressions */
 /***********************/
+/* SYM_REF1(ref_expression_c, exp)  --> an extension to the IEC 61131-3 standard - based on the IEC 61131-3 v3 standard. Returns address of the varible! */
+void *print_datatypes_error_c::visit(  ref_expression_c  *symbol) {
+	symbol->exp->accept(*this);
+	/* we should really check whether the expression is merely a variable. For now, leave it for the future! */
+	if ((symbol->candidate_datatypes.size() == 0) && (symbol->exp->candidate_datatypes.size() > 0))
+		STAGE3_ERROR(0, symbol, symbol, "REF operator must be used with a variable.");
+	return NULL;
+}
+    
 
 void *print_datatypes_error_c::print_binary_expression_errors(const char *operation, symbol_c *symbol, symbol_c *l_expr, symbol_c *r_expr, bool deprecated_operation) {
 	l_expr->accept(*this);
--- a/stage3/print_datatypes_error.hh	Mon Feb 24 22:00:55 2014 +0000
+++ b/stage3/print_datatypes_error.hh	Sun Mar 02 16:42:56 2014 +0000
@@ -283,6 +283,7 @@
     /***********************/
     /* B 3.1 - Expressions */
     /***********************/
+    void *visit(ref_expression_c *symbol);
     void *visit(or_expression_c *symbol);
     void *visit(xor_expression_c *symbol);
     void *visit(and_expression_c *symbol);
--- a/stage4/generate_c/generate_c.cc	Mon Feb 24 22:00:55 2014 +0000
+++ b/stage4/generate_c/generate_c.cc	Sun Mar 02 16:42:56 2014 +0000
@@ -132,6 +132,12 @@
 #define GET_EXTERNAL "__GET_EXTERNAL"
 #define GET_EXTERNAL_FB "__GET_EXTERNAL_FB"
 #define GET_LOCATED "__GET_LOCATED"
+
+#define GET_VAR_REF "__GET_VAR_REF"
+#define GET_EXTERNAL_REF "__GET_EXTERNAL_REF"
+#define GET_EXTERNAL_FB_REF "__GET_EXTERNAL_FB_REF"
+#define GET_LOCATED_REF "__GET_LOCATED_REF"
+
 #define GET_VAR_BY_REF "__GET_VAR_BY_REF"
 #define GET_EXTERNAL_BY_REF "__GET_EXTERNAL_BY_REF"
 #define GET_EXTERNAL_FB_BY_REF "__GET_EXTERNAL_FB_BY_REF"
--- a/stage4/generate_c/generate_c_st.cc	Mon Feb 24 22:00:55 2014 +0000
+++ b/stage4/generate_c/generate_c_st.cc	Sun Mar 02 16:42:56 2014 +0000
@@ -456,6 +456,47 @@
 /***********************/
 /* B 3.1 - Expressions */
 /***********************/
+void *visit(ref_expression_c *symbol) {
+  s4o.print("((IEC_UDINT)");  
+  if (this->is_variable_prefix_null()) {  
+    /* For code in FUNCTIONs */
+    s4o.print("&(");  
+    symbol->exp->accept(*this);    
+    s4o.print(")");  
+  } else {
+    /* For code in FBs, and PROGRAMS... */
+    s4o.print("(");  
+    unsigned int vartype = analyse_variable_c::first_nonfb_vardecltype(symbol->exp, scope_);
+    if (vartype == search_var_instance_decl_c::external_vt) {
+      if (!get_datatype_info_c::is_type_valid    (symbol->exp->datatype)) ERROR;
+      if ( get_datatype_info_c::is_function_block(symbol->exp->datatype))
+        s4o.print(GET_EXTERNAL_FB_REF);
+      else
+        s4o.print(GET_EXTERNAL_REF);
+    }
+    else if (vartype == search_var_instance_decl_c::located_vt)
+      s4o.print(GET_LOCATED_REF);
+    else
+      s4o.print(GET_VAR_REF);
+    
+    variablegeneration_t old_wanted_variablegeneration = wanted_variablegeneration; 
+    s4o.print("(");
+    wanted_variablegeneration = complextype_base_vg;
+    symbol->exp->accept(*this);
+    s4o.print(",");
+    wanted_variablegeneration = complextype_suffix_vg;
+    symbol->exp->accept(*this);
+    s4o.print(")");
+    wanted_variablegeneration = old_wanted_variablegeneration;
+    
+    s4o.print(")");  
+  }
+  s4o.print(")");  
+
+  return NULL;
+}
+
+
 void *visit(or_expression_c *symbol) {
   if (get_datatype_info_c::is_BOOL_compatible(symbol->datatype))
     return print_binary_expression(symbol->l_exp, symbol->r_exp, " || ");
--- a/stage4/generate_iec/generate_iec.cc	Mon Feb 24 22:00:55 2014 +0000
+++ b/stage4/generate_iec/generate_iec.cc	Sun Mar 02 16:42:56 2014 +0000
@@ -1856,6 +1856,7 @@
 /***********************/
 /* B 3.1 - Expressions */
 /***********************/
+void *visit(ref_expression_c *symbol) {return  s4o.print("REF("); symbol->exp->accept(*this); s4o.print(")");} /* an extension to the IEC 61131-3 standard - based on the IEC 61131-3 v3 standard. Returns address of the varible! */
 void *visit(or_expression_c *symbol) {return print_binary_expression(symbol, symbol->l_exp, symbol->r_exp, " OR ");}
 void *visit(xor_expression_c *symbol) {return print_binary_expression(symbol, symbol->l_exp, symbol->r_exp, " XOR ");}
 void *visit(and_expression_c *symbol) {return print_binary_expression(symbol, symbol->l_exp, symbol->r_exp, " AND ");}