impemented compound assignment operators and prefix increment/decrement for array...
authorVictor Kirhenshtein <victor@netxms.org>
Sun, 29 May 2016 10:50:20 +0000 (13:50 +0300)
committerVictor Kirhenshtein <victor@netxms.org>
Sun, 29 May 2016 10:50:20 +0000 (13:50 +0300)
ChangeLog
src/libnxsl/libnxsl.h
src/libnxsl/parser.y
src/libnxsl/program.cpp
src/libnxsl/vm.cpp

index 24c051a..237f56e 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -17,6 +17,7 @@
 - Fixed bugs in LLDP based network topology discovery
 - Correct notifications on threshold script errors
 - Option to use last known value for cluster data aggregation in case of data collecion failure
+- NXSL: implemented compound assignment operators and prefix increment/decrement for array elements
 - Management console
        - Improved dashboard gauge widget
        - Added translucence option for dashboard line charts
@@ -27,7 +28,7 @@
        - Object tooltips in rack view
 - Android console
        - Reorganized alarm notification section (issue #1194)
-- Fixed issues: #859, #984, #1086, #1186, #1194, #1195, #1196, #1197, #1200, #1209, #1210, #1214, #1223, #1227, #1231
+- Fixed issues: #405, #859, #984, #1086, #1186, #1194, #1195, #1196, #1197, #1200, #1209, #1210, #1214, #1223, #1227, #1231
 
 
 *
index ac3442c..9c6434e 100644 (file)
@@ -132,6 +132,7 @@ typedef void *yyscan_t;
 #define OPCODE_STORAGE_INCP   79
 #define OPCODE_STORAGE_DEC    80
 #define OPCODE_STORAGE_DECP   81
+#define OPCODE_PEEK_ELEMENT   82
 
 class NXSL_Compiler;
 
index 8c38f80..f85e403 100644 (file)
@@ -403,6 +403,46 @@ Expression:
 {
        pScript->addInstruction(new NXSL_Instruction(pLexer->getCurrLine(), OPCODE_SET_ELEMENT));
 }
+|      Expression '[' Expression ']' T_ASSIGN_ADD { pScript->addInstruction(new NXSL_Instruction(pLexer->getCurrLine(), OPCODE_PEEK_ELEMENT)); } Expression
+{
+       pScript->addInstruction(new NXSL_Instruction(pLexer->getCurrLine(), OPCODE_ADD));
+       pScript->addInstruction(new NXSL_Instruction(pLexer->getCurrLine(), OPCODE_SET_ELEMENT));
+}
+|      Expression '[' Expression ']' T_ASSIGN_SUB { pScript->addInstruction(new NXSL_Instruction(pLexer->getCurrLine(), OPCODE_PEEK_ELEMENT)); } Expression
+{
+       pScript->addInstruction(new NXSL_Instruction(pLexer->getCurrLine(), OPCODE_SUB));
+       pScript->addInstruction(new NXSL_Instruction(pLexer->getCurrLine(), OPCODE_SET_ELEMENT));
+}
+|      Expression '[' Expression ']' T_ASSIGN_MUL { pScript->addInstruction(new NXSL_Instruction(pLexer->getCurrLine(), OPCODE_PEEK_ELEMENT)); } Expression
+{
+       pScript->addInstruction(new NXSL_Instruction(pLexer->getCurrLine(), OPCODE_MUL));
+       pScript->addInstruction(new NXSL_Instruction(pLexer->getCurrLine(), OPCODE_SET_ELEMENT));
+}
+|      Expression '[' Expression ']' T_ASSIGN_DIV { pScript->addInstruction(new NXSL_Instruction(pLexer->getCurrLine(), OPCODE_PEEK_ELEMENT)); } Expression
+{
+       pScript->addInstruction(new NXSL_Instruction(pLexer->getCurrLine(), OPCODE_DIV));
+       pScript->addInstruction(new NXSL_Instruction(pLexer->getCurrLine(), OPCODE_SET_ELEMENT));
+}
+|      Expression '[' Expression ']' T_ASSIGN_CONCAT { pScript->addInstruction(new NXSL_Instruction(pLexer->getCurrLine(), OPCODE_PEEK_ELEMENT)); } Expression
+{
+       pScript->addInstruction(new NXSL_Instruction(pLexer->getCurrLine(), OPCODE_CONCAT));
+       pScript->addInstruction(new NXSL_Instruction(pLexer->getCurrLine(), OPCODE_SET_ELEMENT));
+}
+|      Expression '[' Expression ']' T_ASSIGN_AND { pScript->addInstruction(new NXSL_Instruction(pLexer->getCurrLine(), OPCODE_PEEK_ELEMENT)); } Expression
+{
+       pScript->addInstruction(new NXSL_Instruction(pLexer->getCurrLine(), OPCODE_BIT_AND));
+       pScript->addInstruction(new NXSL_Instruction(pLexer->getCurrLine(), OPCODE_SET_ELEMENT));
+}
+|      Expression '[' Expression ']' T_ASSIGN_OR { pScript->addInstruction(new NXSL_Instruction(pLexer->getCurrLine(), OPCODE_PEEK_ELEMENT)); } Expression
+{
+       pScript->addInstruction(new NXSL_Instruction(pLexer->getCurrLine(), OPCODE_BIT_OR));
+       pScript->addInstruction(new NXSL_Instruction(pLexer->getCurrLine(), OPCODE_SET_ELEMENT));
+}
+|      Expression '[' Expression ']' T_ASSIGN_XOR { pScript->addInstruction(new NXSL_Instruction(pLexer->getCurrLine(), OPCODE_PEEK_ELEMENT)); } Expression
+{
+       pScript->addInstruction(new NXSL_Instruction(pLexer->getCurrLine(), OPCODE_BIT_XOR));
+       pScript->addInstruction(new NXSL_Instruction(pLexer->getCurrLine(), OPCODE_SET_ELEMENT));
+}
 |      Expression '[' Expression ']'
 {
        pScript->addInstruction(new NXSL_Instruction(pLexer->getCurrLine(), OPCODE_GET_ELEMENT));
@@ -488,16 +528,14 @@ Expression:
 {
        pScript->addInstruction(new NXSL_Instruction(pLexer->getCurrLine(), OPCODE_STORAGE_DEC));
 }
-/*
-|      T_INC Expression '[' Expression ']'
+|      T_INC '(' Expression '[' Expression ']' ')'
 {
        pScript->addInstruction(new NXSL_Instruction(pLexer->getCurrLine(), OPCODE_INCP_ELEMENT));
 }
-|      T_DEC Expression '[' Expression ']'
+|      T_DEC '(' Expression '[' Expression ']' ')'
 {
        pScript->addInstruction(new NXSL_Instruction(pLexer->getCurrLine(), OPCODE_DECP_ELEMENT));
 }
-*/
 |      Expression '[' Expression ']' T_INC     %prec T_POST_INC
 {
        pScript->addInstruction(new NXSL_Instruction(pLexer->getCurrLine(), OPCODE_INC_ELEMENT));
index 4967060..5f9655c 100644 (file)
@@ -52,7 +52,7 @@ const char *g_nxslCommandMnemonic[] =
    "EINCP", "EDECP", "ABORT", "CATCH", "PUSH",
    "SETHM", "NEWARR", "NEWHM", "CPOP",
    "SREAD", "SWRITE", "SELECT", "PUSHCP",
-   "SINC", "SINCP", "SDEC", "SDECP"
+   "SINC", "SINCP", "SDEC", "SDECP", "EPEEK"
 };
 
 /**
index f8f7d70..88ed219 100644 (file)
@@ -689,6 +689,36 @@ void NXSL_VM::execute()
             error(NXSL_ERR_DATA_STACK_UNDERFLOW);
          }
                        break;
+      case OPCODE_PEEK_ELEMENT:   // Get array or map element keeping array and index on stack; stack should contain: array index (top) (or hashmap key (top))
+         pValue = (NXSL_Value *)m_dataStack->peek();
+         if (pValue != NULL)
+         {
+            NXSL_Value *container = (NXSL_Value *)m_dataStack->peekAt(2);
+            if (container != NULL)
+            {
+               if (container->isArray())
+               {
+                  getOrUpdateArrayElement(cp->m_nOpCode, container, pValue);
+               }
+               else if (container->isHashMap())
+               {
+                  getOrUpdateHashMapElement(cp->m_nOpCode, container, pValue);
+               }
+               else
+               {
+                  error(NXSL_ERR_NOT_CONTAINER);
+               }
+            }
+            else
+            {
+               error(NXSL_ERR_DATA_STACK_UNDERFLOW);
+            }
+         }
+         else
+         {
+            error(NXSL_ERR_DATA_STACK_UNDERFLOW);
+         }
+         break;
                case OPCODE_ADD_TO_ARRAY:  // add element on stack top to array; stack should contain: array new_value (top)
          pValue = (NXSL_Value *)m_dataStack->pop();
          if (pValue != NULL)
@@ -1389,7 +1419,7 @@ void NXSL_VM::getOrUpdateArrayElement(int opcode, NXSL_Value *array, NXSL_Value
 {
        if (index->isInteger())
        {
-      if (opcode != OPCODE_GET_ELEMENT)
+      if ((opcode != OPCODE_GET_ELEMENT) && (opcode != OPCODE_PEEK_ELEMENT))
          array->copyOnWrite();
                NXSL_Value *element = array->getValueAsArray()->get(index->getValueAsInt32());
 
@@ -1474,7 +1504,7 @@ void NXSL_VM::getOrUpdateHashMapElement(int opcode, NXSL_Value *hashMap, NXSL_Va
 {
        if (key->isString())
        {
-      if (opcode != OPCODE_GET_ELEMENT)
+      if ((opcode != OPCODE_GET_ELEMENT) && (opcode != OPCODE_PEEK_ELEMENT))
          hashMap->copyOnWrite();
                NXSL_Value *element = hashMap->getValueAsHashMap()->get(key->getValueAsCString());