diff --git a/server/src/exprtk.hpp b/server/src/exprtk.hpp
index eebadb5..b4530ba 100644
--- a/server/src/exprtk.hpp
+++ b/server/src/exprtk.hpp
@@ -2,7 +2,7 @@
  ******************************************************************
  *           C++ Mathematical Expression Toolkit Library          *
  *                                                                *
- * Author: Arash Partow (1999-2022)                               *
+ * Author: Arash Partow (1999-2023)                               *
  * URL: https://www.partow.net/programming/exprtk/index.html      *
  *                                                                *
  * Copyright notice:                                              *
@@ -38,7 +38,6 @@
 #include <cassert>
 #include <cctype>
 #include <cmath>
-#include <complex>
 #include <cstdio>
 #include <cstdlib>
 #include <cstring>
@@ -298,7 +297,6 @@ namespace exprtk
 
          std::reverse(result.begin(), result.end());
 
-
          return result;
       }
 
@@ -401,7 +399,7 @@ namespace exprtk
       {
       public:
 
-         build_string(const std::size_t& initial_size = 64)
+         explicit build_string(const std::size_t& initial_size = 64)
          {
             data_.reserve(initial_size);
          }
@@ -597,15 +595,13 @@ namespace exprtk
          }
       };
 
-      template <typename Compare,
-                typename Iterator,
-                typename ValueType = typename std::iterator_traits<Iterator>::value_type>
+      template <typename Iterator, typename Compare>
       inline bool match_impl(const Iterator pattern_begin,
                              const Iterator pattern_end  ,
                              const Iterator data_begin   ,
                              const Iterator data_end     ,
-                             const ValueType zero_or_more,
-                             const ValueType exactly_one )
+                             const typename std::iterator_traits<Iterator>::value_type& zero_or_more,
+                             const typename std::iterator_traits<Iterator>::value_type& exactly_one )
       {
          typedef typename std::iterator_traits<Iterator>::value_type type;
 
@@ -665,7 +661,7 @@ namespace exprtk
       inline bool wc_match(const std::string& wild_card,
                            const std::string& str)
       {
-         return match_impl<cs_match>(
+         return match_impl<char_cptr,cs_match>(
                    wild_card.data(),
                    wild_card.data() + wild_card.size(),
                    str.data(),
@@ -676,7 +672,7 @@ namespace exprtk
       inline bool wc_imatch(const std::string& wild_card,
                             const std::string& str)
       {
-         return match_impl<cis_match>(
+         return match_impl<char_cptr,cis_match>(
                    wild_card.data(),
                    wild_card.data() + wild_card.size(),
                    str.data(),
@@ -784,7 +780,6 @@ namespace exprtk
          {
             struct unknown_type_tag { unknown_type_tag() {} };
             struct real_type_tag    { real_type_tag   () {} };
-            struct complex_type_tag { complex_type_tag() {} };
             struct int_type_tag     { int_type_tag    () {} };
 
             template <typename T>
@@ -798,10 +793,6 @@ namespace exprtk
             template <> struct number_type<T>                    \
             { typedef real_type_tag type; number_type() {} };    \
 
-            #define exprtk_register_complex_type_tag(T)          \
-            template <> struct number_type<std::complex<T> >     \
-            { typedef complex_type_tag type; number_type() {} }; \
-
             #define exprtk_register_int_type_tag(T)              \
             template <> struct number_type<T>                    \
             { typedef int_type_tag type; number_type() {} };     \
@@ -810,10 +801,6 @@ namespace exprtk
             exprtk_register_real_type_tag(long double)
             exprtk_register_real_type_tag(float      )
 
-            exprtk_register_complex_type_tag(double     )
-            exprtk_register_complex_type_tag(long double)
-            exprtk_register_complex_type_tag(float      )
-
             exprtk_register_int_type_tag(short         )
             exprtk_register_int_type_tag(int           )
             exprtk_register_int_type_tag(_int64_t      )
@@ -2073,6 +2060,11 @@ namespace exprtk
          details::_uint64_t iteration_count;
       };
 
+      virtual bool check()
+      {
+         return true;
+      }
+
       virtual void handle_runtime_violation(const violation_context&)
       {
          throw std::runtime_error("ExprTk Loop run-time violation.");
@@ -3328,7 +3320,7 @@ namespace exprtk
                ignore_set_.insert(symbol);
             }
 
-            inline int insert(const lexer::token& t0, const lexer::token& t1, lexer::token& new_token)
+            inline int insert(const lexer::token& t0, const lexer::token& t1, lexer::token& new_token) exprtk_override
             {
                bool match         = false;
                new_token.type     = lexer::token::e_mul;
@@ -3383,7 +3375,7 @@ namespace exprtk
             : token_joiner(stride)
             {}
 
-            inline bool join(const lexer::token& t0, const lexer::token& t1, lexer::token& t)
+            inline bool join(const lexer::token& t0, const lexer::token& t1, lexer::token& t) exprtk_override
             {
                // ': =' --> ':='
                if ((t0.type == lexer::token::e_colon) && (t1.type == lexer::token::e_eq))
@@ -3531,7 +3523,7 @@ namespace exprtk
             inline bool join(const lexer::token& t0,
                              const lexer::token& t1,
                              const lexer::token& t2,
-                             lexer::token& t)
+                             lexer::token& t) exprtk_override
             {
                // '[ * ]' --> '[*]'
                if (
@@ -3637,7 +3629,7 @@ namespace exprtk
          };
 
          template <typename T>
-         class numeric_checker : public lexer::token_scanner
+         class numeric_checker exprtk_final : public lexer::token_scanner
          {
          public:
 
@@ -3767,7 +3759,7 @@ namespace exprtk
             replace_map_t replace_map_;
          };
 
-         class sequence_validator : public lexer::token_scanner
+         class sequence_validator exprtk_final : public lexer::token_scanner
          {
          private:
 
@@ -3939,7 +3931,7 @@ namespace exprtk
             std::vector<std::pair<lexer::token,lexer::token> > error_list_;
          };
 
-         class sequence_validator_3tokens : public lexer::token_scanner
+         class sequence_validator_3tokens exprtk_final : public lexer::token_scanner
          {
          private:
 
@@ -4773,12 +4765,12 @@ namespace exprtk
       inline void dump_ptr(const std::string& s, const void* ptr, const std::size_t size = 0)
       {
          if (size)
-            exprtk_debug(("%s - addr: %p\n",s.c_str(),ptr));
-         else
             exprtk_debug(("%s - addr: %p size: %d\n",
                           s.c_str(),
                           ptr,
                           static_cast<unsigned int>(size)));
+         else
+            exprtk_debug(("%s - addr: %p\n",s.c_str(),ptr));
       }
       #else
       inline void dump_ptr(const std::string&, const void*) {}
@@ -4822,7 +4814,7 @@ namespace exprtk
             {
                if (data && destruct && (0 == ref_count))
                {
-                  dump_ptr("~control_block() data",data);
+                  dump_ptr("~vec_data_store::control_block() data",data);
                   delete[] data;
                   data = reinterpret_cast<data_t>(0);
                }
@@ -5235,12 +5227,6 @@ namespace exprtk
          return std::not_equal_to<float>()(0.0f,v);
       }
 
-      template <typename T>
-      inline bool is_true(const std::complex<T>& v)
-      {
-         return std::not_equal_to<std::complex<T> >()(std::complex<T>(0),v);
-      }
-
       template <typename T>
       inline bool is_true(const expression_node<T>* node)
       {
@@ -5957,16 +5943,16 @@ namespace exprtk
          : vector_holder_base_(new(buffer)array_vector_impl(vec,vec_size))
          {}
 
-         vector_holder(const vds_t& vds)
+         explicit vector_holder(const vds_t& vds)
          : vector_holder_base_(new(buffer)array_vector_impl(vds.data(),vds.size()))
          {}
 
          template <typename Allocator>
-         vector_holder(std::vector<Type,Allocator>& vec)
+         explicit vector_holder(std::vector<Type,Allocator>& vec)
          : vector_holder_base_(new(buffer)sequence_vector_impl<Allocator,std::vector>(vec))
          {}
 
-         vector_holder(exprtk::vector_view<Type>& vec)
+         explicit vector_holder(exprtk::vector_view<Type>& vec)
          : vector_holder_base_(new(buffer)vector_view_impl(vec))
          {}
 
@@ -6084,9 +6070,9 @@ namespace exprtk
             const bool result = details::numeric::is_nan(v);
 
             if (result)
-               return (equality_) ? T(1) : T(0);
+               return equality_ ? T(1) : T(0);
             else
-               return (equality_) ? T(0) : T(1);
+               return equality_ ? T(0) : T(1);
          }
 
          inline typename expression_node<T>::node_type type() const exprtk_override
@@ -6270,9 +6256,7 @@ namespace exprtk
          inline T value() const exprtk_override
          {
             assert(branch_.first);
-
             const T arg = branch_.first->value();
-
             return numeric::process<T>(operation_,arg);
          }
 
@@ -6301,12 +6285,12 @@ namespace exprtk
             expression_node<T>::ndb_t::collect(branch_, node_delete_list);
          }
 
-         std::size_t node_depth() const exprtk_override exprtk_final
+         std::size_t node_depth() const exprtk_final
          {
             return expression_node<T>::ndb_t::compute_node_depth(branch_);
          }
 
-      protected:
+      private:
 
          operator_type operation_;
          branch_t branch_;
@@ -6336,7 +6320,7 @@ namespace exprtk
             const T arg0 = branch_[0].first->value();
             const T arg1 = branch_[1].first->value();
 
-            return numeric::process<T>(operation_,arg0,arg1);
+            return numeric::process<T>(operation_, arg0, arg1);
          }
 
          inline typename expression_node<T>::node_type type() const exprtk_override
@@ -6364,12 +6348,12 @@ namespace exprtk
             expression_node<T>::ndb_t::template collect(branch_, node_delete_list);
          }
 
-         std::size_t node_depth() const exprtk_override exprtk_final
+         std::size_t node_depth() const exprtk_final
          {
             return expression_node<T>::ndb_t::template compute_node_depth<2>(branch_);
          }
 
-      protected:
+      private:
 
          operator_type operation_;
          branch_t branch_[2];
@@ -6748,7 +6732,7 @@ namespace exprtk
          {
             if (
                  (0 == loop_runtime_check_) ||
-                 (++iteration_count_ <= max_loop_iterations_)
+                 ((++iteration_count_ <= max_loop_iterations_) && loop_runtime_check_->check())
                )
             {
                return true;
@@ -8184,6 +8168,8 @@ namespace exprtk
          typedef vector_node    <T>* vector_node_ptr;
          typedef vec_data_store <T>  vds_t;
 
+         using binary_node<T>::branch;
+
          swap_vecvec_node(expression_ptr branch0,
                           expression_ptr branch1)
          : binary_node<T>(details::e_swap, branch0, branch1)
@@ -8192,22 +8178,22 @@ namespace exprtk
          , vec_size_     (0)
          , initialised_  (false)
          {
-            if (is_ivector_node(binary_node<T>::branch_[0].first))
+            if (is_ivector_node(branch(0)))
             {
                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
 
-               if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[0].first)))
+               if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(0))))
                {
                   vec0_node_ptr_ = vi->vec();
                   vds()          = vi->vds();
                }
             }
 
-            if (is_ivector_node(binary_node<T>::branch_[1].first))
+            if (is_ivector_node(branch(1)))
             {
                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
 
-               if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
+               if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(1))))
                {
                   vec1_node_ptr_ = vi->vec();
                }
@@ -8228,11 +8214,11 @@ namespace exprtk
          {
             if (initialised_)
             {
-               assert(binary_node<T>::branch_[0].first);
-               assert(binary_node<T>::branch_[1].first);
+               assert(branch(0));
+               assert(branch(1));
 
-               binary_node<T>::branch_[0].first->value();
-               binary_node<T>::branch_[1].first->value();
+               binary_node<T>::branch(0)->value();
+               binary_node<T>::branch(1)->value();
 
                T* vec0 = vec0_node_ptr_->vds().data();
                T* vec1 = vec1_node_ptr_->vds().data();
@@ -8693,6 +8679,8 @@ namespace exprtk
          typedef expression_node <T>* expression_ptr;
          typedef string_base_node<T>* str_base_ptr;
 
+         using binary_node<T>::branch;
+
          string_concat_node(const operator_type& opr,
                             expression_ptr branch0,
                             expression_ptr branch1)
@@ -8709,27 +8697,27 @@ namespace exprtk
             range_.cache.first  = range_.n0_c.second;
             range_.cache.second = range_.n1_c.second;
 
-            if (is_generally_string_node(binary_node<T>::branch_[0].first))
+            if (is_generally_string_node(branch(0)))
             {
-               str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
+               str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0));
 
                if (0 == str0_base_ptr_)
                   return;
 
-               str0_range_ptr_ = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);
+               str0_range_ptr_ = dynamic_cast<irange_ptr>(branch(0));
 
                if (0 == str0_range_ptr_)
                   return;
             }
 
-            if (is_generally_string_node(binary_node<T>::branch_[1].first))
+            if (is_generally_string_node(branch(1)))
             {
-               str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);
+               str1_base_ptr_ = dynamic_cast<str_base_ptr>(branch(1));
 
                if (0 == str1_base_ptr_)
                   return;
 
-               str1_range_ptr_ = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
+               str1_range_ptr_ = dynamic_cast<irange_ptr>(branch(1));
 
                if (0 == str1_range_ptr_)
                   return;
@@ -8747,11 +8735,11 @@ namespace exprtk
          {
             if (initialised_)
             {
-               assert(binary_node<T>::branch_[0].first);
-               assert(binary_node<T>::branch_[1].first);
+               assert(branch(0));
+               assert(branch(1));
 
-               binary_node<T>::branch_[0].first->value();
-               binary_node<T>::branch_[1].first->value();
+               branch(0)->value();
+               branch(1)->value();
 
                std::size_t str0_r0 = 0;
                std::size_t str0_r1 = 0;
@@ -8838,20 +8826,22 @@ namespace exprtk
          typedef stringvar_node  <T>* strvar_node_ptr;
          typedef string_base_node<T>* str_base_ptr;
 
+         using binary_node<T>::branch;
+
          swap_string_node(expression_ptr branch0, expression_ptr branch1)
          : binary_node<T>(details::e_swap, branch0, branch1),
            initialised_(false),
            str0_node_ptr_(0),
            str1_node_ptr_(0)
          {
-            if (is_string_node(binary_node<T>::branch_[0].first))
+            if (is_string_node(branch(0)))
             {
-               str0_node_ptr_ = static_cast<strvar_node_ptr>(binary_node<T>::branch_[0].first);
+               str0_node_ptr_ = static_cast<strvar_node_ptr>(branch(0));
             }
 
-            if (is_string_node(binary_node<T>::branch_[1].first))
+            if (is_string_node(branch(1)))
             {
-               str1_node_ptr_ = static_cast<strvar_node_ptr>(binary_node<T>::branch_[1].first);
+               str1_node_ptr_ = static_cast<strvar_node_ptr>(branch(1));
             }
 
             initialised_ = (str0_node_ptr_ && str1_node_ptr_);
@@ -8863,11 +8853,11 @@ namespace exprtk
          {
             if (initialised_)
             {
-               assert(binary_node<T>::branch_[0].first);
-               assert(binary_node<T>::branch_[1].first);
+               assert(branch(0));
+               assert(branch(1));
 
-               binary_node<T>::branch_[0].first->value();
-               binary_node<T>::branch_[1].first->value();
+               branch(0)->value();
+               branch(1)->value();
 
                std::swap(str0_node_ptr_->ref(), str1_node_ptr_->ref());
             }
@@ -8924,6 +8914,8 @@ namespace exprtk
          typedef expression_node <T>* expression_ptr;
          typedef string_base_node<T>* str_base_ptr;
 
+         using binary_node<T>::branch;
+
          swap_genstrings_node(expression_ptr branch0,
                               expression_ptr branch1)
          : binary_node<T>(details::e_default, branch0, branch1)
@@ -8933,14 +8925,14 @@ namespace exprtk
          , str1_range_ptr_(0)
          , initialised_(false)
          {
-            if (is_generally_string_node(binary_node<T>::branch_[0].first))
+            if (is_generally_string_node(branch(0)))
             {
-               str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
+               str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0));
 
                if (0 == str0_base_ptr_)
                   return;
 
-               irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);
+               irange_ptr range = dynamic_cast<irange_ptr>(branch(0));
 
                if (0 == range)
                   return;
@@ -8948,14 +8940,14 @@ namespace exprtk
                str0_range_ptr_ = &(range->range_ref());
             }
 
-            if (is_generally_string_node(binary_node<T>::branch_[1].first))
+            if (is_generally_string_node(branch(1)))
             {
-               str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);
+               str1_base_ptr_ = dynamic_cast<str_base_ptr>(branch(1));
 
                if (0 == str1_base_ptr_)
                   return;
 
-               irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
+               irange_ptr range = dynamic_cast<irange_ptr>(branch(1));
 
                if (0 == range)
                   return;
@@ -8975,11 +8967,11 @@ namespace exprtk
          {
             if (initialised_)
             {
-               assert(binary_node<T>::branch_[0].first);
-               assert(binary_node<T>::branch_[1].first);
+               assert(branch(0));
+               assert(branch(1));
 
-               binary_node<T>::branch_[0].first->value();
-               binary_node<T>::branch_[1].first->value();
+               branch(0)->value();
+               branch(1)->value();
 
                std::size_t str0_r0 = 0;
                std::size_t str0_r1 = 0;
@@ -9189,6 +9181,8 @@ namespace exprtk
          typedef stringvar_node  <T>* strvar_node_ptr;
          typedef string_base_node<T>* str_base_ptr;
 
+         using binary_node<T>::branch;
+
          assignment_string_node(const operator_type& opr,
                                 expression_ptr branch0,
                                 expression_ptr branch1)
@@ -9199,21 +9193,20 @@ namespace exprtk
          , str0_node_ptr_ (0)
          , str1_range_ptr_(0)
          {
-            if (is_string_node(binary_node<T>::branch_[0].first))
+            if (is_string_node(branch(0)))
             {
-               str0_node_ptr_ = static_cast<strvar_node_ptr>(binary_node<T>::branch_[0].first);
-
-               str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
+               str0_node_ptr_ = static_cast<strvar_node_ptr>(branch(0));
+               str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0));
             }
 
-            if (is_generally_string_node(binary_node<T>::branch_[1].first))
+            if (is_generally_string_node(branch(1)))
             {
-               str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);
+               str1_base_ptr_ = dynamic_cast<str_base_ptr>(branch(1));
 
                if (0 == str1_base_ptr_)
                   return;
 
-               irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
+               irange_ptr range = dynamic_cast<irange_ptr>(branch(1));
 
                if (0 == range)
                   return;
@@ -9233,10 +9226,10 @@ namespace exprtk
          {
             if (initialised_)
             {
-               assert(binary_node<T>::branch_[0].first);
-               assert(binary_node<T>::branch_[1].first);
+               assert(branch(0));
+               assert(branch(1));
 
-               binary_node<T>::branch_[1].first->value();
+               branch(1)->value();
 
                std::size_t r0 = 0;
                std::size_t r1 = 0;
@@ -9249,7 +9242,7 @@ namespace exprtk
                                              str1_base_ptr_->base() + r0,
                                              (r1 - r0) + 1);
 
-                  binary_node<T>::branch_[0].first->value();
+                  branch(0)->value();
                }
             }
 
@@ -9312,6 +9305,8 @@ namespace exprtk
          typedef string_range_node<T>* str_rng_node_ptr;
          typedef string_base_node <T>* str_base_ptr;
 
+         using binary_node<T>::branch;
+
          assignment_string_range_node(const operator_type& opr,
                                       expression_ptr branch0,
                                       expression_ptr branch1)
@@ -9323,13 +9318,11 @@ namespace exprtk
          , str0_range_ptr_   (0)
          , str1_range_ptr_   (0)
          {
-            if (is_string_range_node(binary_node<T>::branch_[0].first))
+            if (is_string_range_node(branch(0)))
             {
-               str0_rng_node_ptr_ = static_cast<str_rng_node_ptr>(binary_node<T>::branch_[0].first);
-
-               str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
-
-               irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);
+               str0_rng_node_ptr_ = static_cast<str_rng_node_ptr>(branch(0));
+               str0_base_ptr_     = dynamic_cast<str_base_ptr>(branch(0));
+               irange_ptr range   = dynamic_cast<irange_ptr>(branch(0));
 
                if (0 == range)
                   return;
@@ -9337,14 +9330,14 @@ namespace exprtk
                str0_range_ptr_ = &(range->range_ref());
             }
 
-            if (is_generally_string_node(binary_node<T>::branch_[1].first))
+            if (is_generally_string_node(branch(1)))
             {
-               str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);
+               str1_base_ptr_ = dynamic_cast<str_base_ptr>(branch(1));
 
                if (0 == str1_base_ptr_)
                   return;
 
-               irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
+               irange_ptr range = dynamic_cast<irange_ptr>(branch(1));
 
                if (0 == range)
                   return;
@@ -9365,11 +9358,11 @@ namespace exprtk
          {
             if (initialised_)
             {
-               assert(binary_node<T>::branch_[0].first);
-               assert(binary_node<T>::branch_[1].first);
+               assert(branch(0));
+               assert(branch(1));
 
-               binary_node<T>::branch_[0].first->value();
-               binary_node<T>::branch_[1].first->value();
+               branch(0)->value();
+               branch(1)->value();
 
                std::size_t s0_r0 = 0;
                std::size_t s0_r1 = 0;
@@ -9616,6 +9609,8 @@ namespace exprtk
          typedef expression_node <T>* expression_ptr;
          typedef string_base_node<T>* str_base_ptr;
 
+         using binary_node<T>::branch;
+
          cons_conditional_str_node(expression_ptr condition,
                                    expression_ptr consequent)
          : binary_node<T>(details::e_default, consequent, condition)
@@ -9631,14 +9626,14 @@ namespace exprtk
             range_.cache.first  = range_.n0_c.second;
             range_.cache.second = range_.n1_c.second;
 
-            if (is_generally_string_node(binary_node<T>::branch_[0].first))
+            if (is_generally_string_node(branch(0)))
             {
-               str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
+               str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0));
 
                if (0 == str0_base_ptr_)
                   return;
 
-               str0_range_ptr_ = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);
+               str0_range_ptr_ = dynamic_cast<irange_ptr>(branch(0));
 
                if (0 == str0_range_ptr_)
                   return;
@@ -10364,6 +10359,7 @@ namespace exprtk
       public:
 
          typedef expression_node<T>* expression_ptr;
+         using binary_node<T>::branch;
 
          assignment_node(const operator_type& opr,
                          expression_ptr branch0,
@@ -10371,9 +10367,9 @@ namespace exprtk
          : binary_node<T>(opr, branch0, branch1)
          , var_node_ptr_(0)
          {
-            if (is_variable_node(binary_node<T>::branch_[0].first))
+            if (is_variable_node(branch(0)))
             {
-               var_node_ptr_ = static_cast<variable_node<T>*>(binary_node<T>::branch_[0].first);
+               var_node_ptr_ = static_cast<variable_node<T>*>(branch(0));
             }
          }
 
@@ -10381,11 +10377,10 @@ namespace exprtk
          {
             if (var_node_ptr_)
             {
-               assert(binary_node<T>::branch_[1].first);
+               assert(branch(1));
 
                T& result = var_node_ptr_->ref();
-
-               result = binary_node<T>::branch_[1].first->value();
+               result = branch(1)->value();
 
                return result;
             }
@@ -10404,6 +10399,7 @@ namespace exprtk
       public:
 
          typedef expression_node<T>* expression_ptr;
+         using binary_node<T>::branch;
 
          assignment_vec_elem_node(const operator_type& opr,
                                   expression_ptr branch0,
@@ -10411,9 +10407,9 @@ namespace exprtk
          : binary_node<T>(opr, branch0, branch1)
          , vec_node_ptr_(0)
          {
-            if (is_vector_elem_node(binary_node<T>::branch_[0].first))
+            if (is_vector_elem_node(branch(0)))
             {
-               vec_node_ptr_ = static_cast<vector_elem_node<T>*>(binary_node<T>::branch_[0].first);
+               vec_node_ptr_ = static_cast<vector_elem_node<T>*>(branch(0));
             }
          }
 
@@ -10421,11 +10417,10 @@ namespace exprtk
          {
             if (vec_node_ptr_)
             {
-               assert(binary_node<T>::branch_[1].first);
+               assert(branch(1));
 
                T& result = vec_node_ptr_->ref();
-
-               result = binary_node<T>::branch_[1].first->value();
+               result = branch(1)->value();
 
                return result;
             }
@@ -10444,6 +10439,7 @@ namespace exprtk
       public:
 
          typedef expression_node<T>* expression_ptr;
+         using expression_node<T>::branch;
 
          assignment_rebasevec_elem_node(const operator_type& opr,
                                         expression_ptr branch0,
@@ -10451,9 +10447,9 @@ namespace exprtk
          : binary_node<T>(opr, branch0, branch1)
          , rbvec_node_ptr_(0)
          {
-            if (is_rebasevector_elem_node(binary_node<T>::branch_[0].first))
+            if (is_rebasevector_elem_node(branch(0)))
             {
-               rbvec_node_ptr_ = static_cast<rebasevector_elem_node<T>*>(binary_node<T>::branch_[0].first);
+               rbvec_node_ptr_ = static_cast<rebasevector_elem_node<T>*>(branch(0));
             }
          }
 
@@ -10461,11 +10457,11 @@ namespace exprtk
          {
             if (rbvec_node_ptr_)
             {
-               assert(binary_node<T>::branch_[1].first);
+               assert(branch(1));
 
                T& result = rbvec_node_ptr_->ref();
 
-               result = binary_node<T>::branch_[1].first->value();
+               result = branch(1)->value();
 
                return result;
             }
@@ -10484,6 +10480,7 @@ namespace exprtk
       public:
 
          typedef expression_node<T>* expression_ptr;
+         using binary_node<T>::branch;
 
          assignment_rebasevec_celem_node(const operator_type& opr,
                                          expression_ptr branch0,
@@ -10491,9 +10488,9 @@ namespace exprtk
          : binary_node<T>(opr, branch0, branch1)
          , rbvec_node_ptr_(0)
          {
-            if (is_rebasevector_celem_node(binary_node<T>::branch_[0].first))
+            if (is_rebasevector_celem_node(branch(0)))
             {
-               rbvec_node_ptr_ = static_cast<rebasevector_celem_node<T>*>(binary_node<T>::branch_[0].first);
+               rbvec_node_ptr_ = static_cast<rebasevector_celem_node<T>*>(branch(0));
             }
          }
 
@@ -10501,11 +10498,10 @@ namespace exprtk
          {
             if (rbvec_node_ptr_)
             {
-               assert(binary_node<T>::branch_[1].first);
+               assert(branch(1));
 
                T& result = rbvec_node_ptr_->ref();
-
-               result = binary_node<T>::branch_[1].first->value();
+               result = branch(1)->value();
 
                return result;
             }
@@ -10529,15 +10525,17 @@ namespace exprtk
          typedef vector_node<T>*     vector_node_ptr;
          typedef vec_data_store<T>   vds_t;
 
+         using binary_node<T>::branch;
+
          assignment_vec_node(const operator_type& opr,
                              expression_ptr branch0,
                              expression_ptr branch1)
          : binary_node<T>(opr, branch0, branch1)
          , vec_node_ptr_(0)
          {
-            if (is_vector_node(binary_node<T>::branch_[0].first))
+            if (is_vector_node(branch(0)))
             {
-               vec_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
+               vec_node_ptr_ = static_cast<vector_node<T>*>(branch(0));
                vds()         = vec_node_ptr_->vds();
             }
          }
@@ -10546,9 +10544,9 @@ namespace exprtk
          {
             if (vec_node_ptr_)
             {
-               assert(binary_node<T>::branch_[1].first);
+               assert(branch(1));
 
-               const T v = binary_node<T>::branch_[1].first->value();
+               const T v = branch(1)->value();
 
                T* vec = vds().data();
 
@@ -10649,6 +10647,8 @@ namespace exprtk
          typedef vector_node<T>*     vector_node_ptr;
          typedef vec_data_store<T>   vds_t;
 
+         using binary_node<T>::branch;
+
          assignment_vecvec_node(const operator_type& opr,
                                 expression_ptr branch0,
                                 expression_ptr branch1)
@@ -10658,22 +10658,22 @@ namespace exprtk
          , initialised_(false)
          , src_is_ivec_(false)
          {
-            if (is_vector_node(binary_node<T>::branch_[0].first))
+            if (is_vector_node(branch(0)))
             {
-               vec0_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
+               vec0_node_ptr_ = static_cast<vector_node<T>*>(branch(0));
                vds()          = vec0_node_ptr_->vds();
             }
 
-            if (is_vector_node(binary_node<T>::branch_[1].first))
+            if (is_vector_node(branch(1)))
             {
-               vec1_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[1].first);
+               vec1_node_ptr_ = static_cast<vector_node<T>*>(branch(1));
                vds_t::match_sizes(vds(),vec1_node_ptr_->vds());
             }
-            else if (is_ivector_node(binary_node<T>::branch_[1].first))
+            else if (is_ivector_node(branch(1)))
             {
                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
 
-               if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
+               if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(1))))
                {
                   vec1_node_ptr_ = vi->vec();
 
@@ -10696,9 +10696,9 @@ namespace exprtk
          {
             if (initialised_)
             {
-               assert(binary_node<T>::branch_[1].first);
+               assert(branch(1));
 
-               binary_node<T>::branch_[1].first->value();
+               branch(1)->value();
 
                if (src_is_ivec_)
                   return vec0_node_ptr_->value();
@@ -10802,6 +10802,7 @@ namespace exprtk
       public:
 
          typedef expression_node<T>* expression_ptr;
+         using binary_node<T>::branch;
 
          assignment_op_node(const operator_type& opr,
                             expression_ptr branch0,
@@ -10809,9 +10810,9 @@ namespace exprtk
          : binary_node<T>(opr, branch0, branch1)
          , var_node_ptr_(0)
          {
-            if (is_variable_node(binary_node<T>::branch_[0].first))
+            if (is_variable_node(branch(0)))
             {
-               var_node_ptr_ = static_cast<variable_node<T>*>(binary_node<T>::branch_[0].first);
+               var_node_ptr_ = static_cast<variable_node<T>*>(branch(0));
             }
          }
 
@@ -10819,10 +10820,10 @@ namespace exprtk
          {
             if (var_node_ptr_)
             {
-               assert(binary_node<T>::branch_[1].first);
+               assert(branch(1));
 
                T& v = var_node_ptr_->ref();
-               v = Operation::process(v,binary_node<T>::branch_[1].first->value());
+               v = Operation::process(v,branch(1)->value());
 
                return v;
             }
@@ -10841,6 +10842,7 @@ namespace exprtk
       public:
 
          typedef expression_node<T>* expression_ptr;
+         using binary_node<T>::branch;
 
          assignment_vec_elem_op_node(const operator_type& opr,
                                      expression_ptr branch0,
@@ -10848,9 +10850,9 @@ namespace exprtk
          : binary_node<T>(opr, branch0, branch1)
          , vec_node_ptr_(0)
          {
-            if (is_vector_elem_node(binary_node<T>::branch_[0].first))
+            if (is_vector_elem_node(branch(0)))
             {
-               vec_node_ptr_ = static_cast<vector_elem_node<T>*>(binary_node<T>::branch_[0].first);
+               vec_node_ptr_ = static_cast<vector_elem_node<T>*>(branch(0));
             }
          }
 
@@ -10858,10 +10860,10 @@ namespace exprtk
          {
             if (vec_node_ptr_)
             {
-               assert(binary_node<T>::branch_[1].first);
+               assert(branch(1));
 
                T& v = vec_node_ptr_->ref();
-                  v = Operation::process(v,binary_node<T>::branch_[1].first->value());
+                  v = Operation::process(v,branch(1)->value());
 
                return v;
             }
@@ -10880,6 +10882,7 @@ namespace exprtk
       public:
 
          typedef expression_node<T>* expression_ptr;
+         using binary_node<T>::branch;
 
          assignment_rebasevec_elem_op_node(const operator_type& opr,
                                            expression_ptr branch0,
@@ -10887,9 +10890,9 @@ namespace exprtk
          : binary_node<T>(opr, branch0, branch1)
          , rbvec_node_ptr_(0)
          {
-            if (is_rebasevector_elem_node(binary_node<T>::branch_[0].first))
+            if (is_rebasevector_elem_node(branch(0)))
             {
-               rbvec_node_ptr_ = static_cast<rebasevector_elem_node<T>*>(binary_node<T>::branch_[0].first);
+               rbvec_node_ptr_ = static_cast<rebasevector_elem_node<T>*>(branch(0));
             }
          }
 
@@ -10897,10 +10900,10 @@ namespace exprtk
          {
             if (rbvec_node_ptr_)
             {
-               assert(binary_node<T>::branch_[1].first);
+               assert(branch(1));
 
                T& v = rbvec_node_ptr_->ref();
-                  v = Operation::process(v,binary_node<T>::branch_[1].first->value());
+                  v = Operation::process(v,branch(1)->value());
 
                return v;
             }
@@ -10919,6 +10922,7 @@ namespace exprtk
       public:
 
          typedef expression_node<T>* expression_ptr;
+         using binary_node<T>::branch;
 
          assignment_rebasevec_celem_op_node(const operator_type& opr,
                                             expression_ptr branch0,
@@ -10926,9 +10930,9 @@ namespace exprtk
          : binary_node<T>(opr, branch0, branch1)
          , rbvec_node_ptr_(0)
          {
-            if (is_rebasevector_celem_node(binary_node<T>::branch_[0].first))
+            if (is_rebasevector_celem_node(branch(0)))
             {
-               rbvec_node_ptr_ = static_cast<rebasevector_celem_node<T>*>(binary_node<T>::branch_[0].first);
+               rbvec_node_ptr_ = static_cast<rebasevector_celem_node<T>*>(branch(0));
             }
          }
 
@@ -10936,10 +10940,10 @@ namespace exprtk
          {
             if (rbvec_node_ptr_)
             {
-               assert(binary_node<T>::branch_[1].first);
+               assert(branch(1));
 
                T& v = rbvec_node_ptr_->ref();
-                  v = Operation::process(v,binary_node<T>::branch_[1].first->value());
+                  v = Operation::process(v,branch(1)->value());
 
                return v;
             }
@@ -10963,15 +10967,17 @@ namespace exprtk
          typedef vector_node<T>*     vector_node_ptr;
          typedef vec_data_store<T>   vds_t;
 
+         using binary_node<T>::branch;
+
          assignment_vec_op_node(const operator_type& opr,
                                 expression_ptr branch0,
                                 expression_ptr branch1)
          : binary_node<T>(opr, branch0, branch1)
          , vec_node_ptr_(0)
          {
-            if (is_vector_node(binary_node<T>::branch_[0].first))
+            if (is_vector_node(branch(0)))
             {
-               vec_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
+               vec_node_ptr_ = static_cast<vector_node<T>*>(branch(0));
                vds()         = vec_node_ptr_->vds();
             }
          }
@@ -10980,9 +10986,9 @@ namespace exprtk
          {
             if (vec_node_ptr_)
             {
-               assert(binary_node<T>::branch_[1].first);
+               assert(branch(1));
 
-               const T v = binary_node<T>::branch_[1].first->value();
+               const T v = branch(1)->value();
 
                T* vec = vds().data();
 
@@ -11088,6 +11094,8 @@ namespace exprtk
          typedef vector_node<T>*     vector_node_ptr;
          typedef vec_data_store<T>   vds_t;
 
+         using binary_node<T>::branch;
+
          assignment_vecvec_op_node(const operator_type& opr,
                                    expression_ptr branch0,
                                    expression_ptr branch1)
@@ -11096,22 +11104,22 @@ namespace exprtk
          , vec1_node_ptr_(0)
          , initialised_(false)
          {
-            if (is_vector_node(binary_node<T>::branch_[0].first))
+            if (is_vector_node(branch(0)))
             {
-               vec0_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
+               vec0_node_ptr_ = static_cast<vector_node<T>*>(branch(0));
                vds()          = vec0_node_ptr_->vds();
             }
 
-            if (is_vector_node(binary_node<T>::branch_[1].first))
+            if (is_vector_node(branch(1)))
             {
-               vec1_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[1].first);
+               vec1_node_ptr_ = static_cast<vector_node<T>*>(branch(1));
                vec1_node_ptr_->vds() = vds();
             }
-            else if (is_ivector_node(binary_node<T>::branch_[1].first))
+            else if (is_ivector_node(branch(1)))
             {
                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
 
-               if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
+               if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(1))))
                {
                   vec1_node_ptr_ = vi->vec();
                   vec1_node_ptr_->vds() = vds();
@@ -11129,11 +11137,11 @@ namespace exprtk
          {
             if (initialised_)
             {
-               assert(binary_node<T>::branch_[0].first);
-               assert(binary_node<T>::branch_[1].first);
+               assert(branch(0));
+               assert(branch(1));
 
-               binary_node<T>::branch_[0].first->value();
-               binary_node<T>::branch_[1].first->value();
+               branch(0)->value();
+               branch(1)->value();
 
                      T* vec0 = vec0_node_ptr_->vds().data();
                const T* vec1 = vec1_node_ptr_->vds().data();
@@ -11246,6 +11254,8 @@ namespace exprtk
          typedef vector_holder<T>*   vector_holder_ptr;
          typedef vec_data_store<T>   vds_t;
 
+         using binary_node<T>::branch;
+
          vec_binop_vecvec_node(const operator_type& opr,
                                expression_ptr branch0,
                                expression_ptr branch1)
@@ -11259,30 +11269,30 @@ namespace exprtk
             bool v0_is_ivec = false;
             bool v1_is_ivec = false;
 
-            if (is_vector_node(binary_node<T>::branch_[0].first))
+            if (is_vector_node(branch(0)))
             {
-               vec0_node_ptr_ = static_cast<vector_node_ptr>(binary_node<T>::branch_[0].first);
+               vec0_node_ptr_ = static_cast<vector_node_ptr>(branch(0));
             }
-            else if (is_ivector_node(binary_node<T>::branch_[0].first))
+            else if (is_ivector_node(branch(0)))
             {
                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
 
-               if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[0].first)))
+               if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(0))))
                {
                   vec0_node_ptr_ = vi->vec();
                   v0_is_ivec     = true;
                }
             }
 
-            if (is_vector_node(binary_node<T>::branch_[1].first))
+            if (is_vector_node(branch(1)))
             {
-               vec1_node_ptr_ = static_cast<vector_node_ptr>(binary_node<T>::branch_[1].first);
+               vec1_node_ptr_ = static_cast<vector_node_ptr>(branch(1));
             }
-            else if (is_ivector_node(binary_node<T>::branch_[1].first))
+            else if (is_ivector_node(branch(1)))
             {
                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
 
-               if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
+               if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(1))))
                {
                   vec1_node_ptr_ = vi->vec();
                   v1_is_ivec     = true;
@@ -11320,11 +11330,11 @@ namespace exprtk
          {
             if (initialised_)
             {
-               assert(binary_node<T>::branch_[0].first);
-               assert(binary_node<T>::branch_[1].first);
+               assert(branch(0));
+               assert(branch(1));
 
-               binary_node<T>::branch_[0].first->value();
-               binary_node<T>::branch_[1].first->value();
+               branch(0)->value();
+               branch(1)->value();
 
                const T* vec0 = vec0_node_ptr_->vds().data();
                const T* vec1 = vec1_node_ptr_->vds().data();
@@ -11436,6 +11446,8 @@ namespace exprtk
          typedef vector_holder<T>*   vector_holder_ptr;
          typedef vec_data_store<T>   vds_t;
 
+         using binary_node<T>::branch;
+
          vec_binop_vecval_node(const operator_type& opr,
                                expression_ptr branch0,
                                expression_ptr branch1)
@@ -11446,15 +11458,15 @@ namespace exprtk
          {
             bool v0_is_ivec = false;
 
-            if (is_vector_node(binary_node<T>::branch_[0].first))
+            if (is_vector_node(branch(0)))
             {
-               vec0_node_ptr_ = static_cast<vector_node_ptr>(binary_node<T>::branch_[0].first);
+               vec0_node_ptr_ = static_cast<vector_node_ptr>(branch(0));
             }
-            else if (is_ivector_node(binary_node<T>::branch_[0].first))
+            else if (is_ivector_node(branch(0)))
             {
                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
 
-               if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[0].first)))
+               if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(0))))
                {
                   vec0_node_ptr_ = vi->vec();
                   v0_is_ivec     = true;
@@ -11483,11 +11495,11 @@ namespace exprtk
          {
             if (vec0_node_ptr_)
             {
-               assert(binary_node<T>::branch_[0].first);
-               assert(binary_node<T>::branch_[1].first);
+               assert(branch(0));
+               assert(branch(1));
 
-                           binary_node<T>::branch_[0].first->value();
-               const T v = binary_node<T>::branch_[1].first->value();
+                           branch(0)->value();
+               const T v = branch(1)->value();
 
                const T* vec0 = vec0_node_ptr_->vds().data();
                      T* vec1 = vds().data();
@@ -11595,6 +11607,8 @@ namespace exprtk
          typedef vector_holder<T>*   vector_holder_ptr;
          typedef vec_data_store<T>   vds_t;
 
+         using binary_node<T>::branch;
+
          vec_binop_valvec_node(const operator_type& opr,
                                expression_ptr branch0,
                                expression_ptr branch1)
@@ -11605,15 +11619,15 @@ namespace exprtk
          {
             bool v1_is_ivec = false;
 
-            if (is_vector_node(binary_node<T>::branch_[1].first))
+            if (is_vector_node(branch(1)))
             {
-               vec1_node_ptr_ = static_cast<vector_node_ptr>(binary_node<T>::branch_[1].first);
+               vec1_node_ptr_ = static_cast<vector_node_ptr>(branch(1));
             }
-            else if (is_ivector_node(binary_node<T>::branch_[1].first))
+            else if (is_ivector_node(branch(1)))
             {
                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
 
-               if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
+               if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(1))))
                {
                   vec1_node_ptr_ = vi->vec();
                   v1_is_ivec     = true;
@@ -11642,11 +11656,11 @@ namespace exprtk
          {
             if (vec1_node_ptr_)
             {
-               assert(binary_node<T>::branch_[0].first);
-               assert(binary_node<T>::branch_[1].first);
+               assert(branch(0));
+               assert(branch(1));
 
-               const T v = binary_node<T>::branch_[0].first->value();
-                           binary_node<T>::branch_[1].first->value();
+               const T v = branch(0)->value();
+                           branch(1)->value();
 
                      T* vec0 = vds().data();
                const T* vec1 = vec1_node_ptr_->vds().data();
@@ -11754,6 +11768,8 @@ namespace exprtk
          typedef vector_holder<T>*   vector_holder_ptr;
          typedef vec_data_store<T>   vds_t;
 
+         using expression_node<T>::branch;
+
          unary_vector_node(const operator_type& opr, expression_ptr branch0)
          : unary_node<T>(opr, branch0)
          , vec0_node_ptr_(0)
@@ -11762,15 +11778,15 @@ namespace exprtk
          {
             bool vec0_is_ivec = false;
 
-            if (is_vector_node(unary_node<T>::branch_.first))
+            if (is_vector_node(branch()))
             {
-               vec0_node_ptr_ = static_cast<vector_node_ptr>(unary_node<T>::branch_.first);
+               vec0_node_ptr_ = static_cast<vector_node_ptr>(branch());
             }
-            else if (is_ivector_node(unary_node<T>::branch_.first))
+            else if (is_ivector_node(branch()))
             {
                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
 
-               if (0 != (vi = dynamic_cast<vector_interface<T>*>(unary_node<T>::branch_.first)))
+               if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch())))
                {
                   vec0_node_ptr_ = vi->vec();
                   vec0_is_ivec   = true;
@@ -11797,9 +11813,9 @@ namespace exprtk
 
          inline T value() const exprtk_override
          {
-            assert(unary_node<T>::branch_.first);
+            assert(branch());
 
-            unary_node<T>::branch_.first->value();
+            branch()->value();
 
             if (vec0_node_ptr_)
             {
@@ -12063,6 +12079,7 @@ namespace exprtk
       public:
 
          typedef expression_node<T>* expression_ptr;
+         using binary_node<T>::branch;
 
          scand_node(const operator_type& opr,
                     expression_ptr branch0,
@@ -12072,14 +12089,14 @@ namespace exprtk
 
          inline T value() const exprtk_override
          {
-            assert(binary_node<T>::branch_[0].first);
-            assert(binary_node<T>::branch_[1].first);
+            assert(branch(0));
+            assert(branch(1));
 
             return (
                      std::not_equal_to<T>()
-                        (T(0),binary_node<T>::branch_[0].first->value()) &&
+                        (T(0),branch(0)->value()) &&
                      std::not_equal_to<T>()
-                        (T(0),binary_node<T>::branch_[1].first->value())
+                        (T(0),branch(1)->value())
                    ) ? T(1) : T(0);
          }
       };
@@ -12090,6 +12107,7 @@ namespace exprtk
       public:
 
          typedef expression_node<T>* expression_ptr;
+         using binary_node<T>::branch;
 
          scor_node(const operator_type& opr,
                    expression_ptr branch0,
@@ -12099,14 +12117,14 @@ namespace exprtk
 
          inline T value() const exprtk_override
          {
-            assert(binary_node<T>::branch_[0].first);
-            assert(binary_node<T>::branch_[1].first);
+            assert(branch(0));
+            assert(branch(1));
 
             return (
                      std::not_equal_to<T>()
-                        (T(0),binary_node<T>::branch_[0].first->value()) ||
+                        (T(0),branch(0)->value()) ||
                      std::not_equal_to<T>()
-                        (T(0),binary_node<T>::branch_[1].first->value())
+                        (T(0),branch(1)->value())
                    ) ? T(1) : T(0);
          }
       };
@@ -13533,7 +13551,7 @@ namespace exprtk
                case 3  : return process_3(arg_list);
                case 4  : return process_4(arg_list);
                case 5  : return process_5(arg_list);
-               default : return vararg_add_op<T>::process(arg_list) / arg_list.size();
+               default : return vararg_add_op<T>::process(arg_list) / T(arg_list.size());
             }
          }
 
@@ -14192,8 +14210,7 @@ namespace exprtk
 
          static inline T process(const ivector_ptr v)
          {
-            const std::size_t vec_size = v->vec()->vds().size();
-
+            const T vec_size = T(v->vec()->vds().size());
             return vec_add_op<T>::process(v) / vec_size;
          }
       };
@@ -16122,6 +16139,8 @@ namespace exprtk
          typedef range_interface <T>  irange_t;
          typedef irange_t*            irange_ptr;
 
+         using binary_node<T>::branch;
+
          str_sogens_node(const operator_type& opr,
                          expression_ptr branch0,
                          expression_ptr branch1)
@@ -16131,14 +16150,14 @@ namespace exprtk
          , str0_range_ptr_(0)
          , str1_range_ptr_(0)
          {
-            if (is_generally_string_node(binary_node<T>::branch_[0].first))
+            if (is_generally_string_node(branch(0)))
             {
-               str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
+               str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0));
 
                if (0 == str0_base_ptr_)
                   return;
 
-               irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);
+               irange_ptr range = dynamic_cast<irange_ptr>(branch(0));
 
                if (0 == range)
                   return;
@@ -16146,14 +16165,14 @@ namespace exprtk
                str0_range_ptr_ = &(range->range_ref());
             }
 
-            if (is_generally_string_node(binary_node<T>::branch_[1].first))
+            if (is_generally_string_node(branch(1)))
             {
-               str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);
+               str1_base_ptr_ = dynamic_cast<str_base_ptr>(branch(1));
 
                if (0 == str1_base_ptr_)
                   return;
 
-               irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
+               irange_ptr range = dynamic_cast<irange_ptr>(branch(1));
 
                if (0 == range)
                   return;
@@ -16171,8 +16190,8 @@ namespace exprtk
                  str1_range_ptr_
                )
             {
-               binary_node<T>::branch_[0].first->value();
-               binary_node<T>::branch_[1].first->value();
+               branch(0)->value();
+               branch(1)->value();
 
                std::size_t str0_r0 = 0;
                std::size_t str0_r1 = 0;
@@ -17292,22 +17311,29 @@ namespace exprtk
    {
    public:
 
-      typedef T (*ff00_functor)();
-      typedef T (*ff01_functor)(T);
-      typedef T (*ff02_functor)(T, T);
-      typedef T (*ff03_functor)(T, T, T);
-      typedef T (*ff04_functor)(T, T, T, T);
-      typedef T (*ff05_functor)(T, T, T, T, T);
-      typedef T (*ff06_functor)(T, T, T, T, T, T);
-      typedef T (*ff07_functor)(T, T, T, T, T, T, T);
-      typedef T (*ff08_functor)(T, T, T, T, T, T, T, T);
-      typedef T (*ff09_functor)(T, T, T, T, T, T, T, T, T);
-      typedef T (*ff10_functor)(T, T, T, T, T, T, T, T, T, T);
-      typedef T (*ff11_functor)(T, T, T, T, T, T, T, T, T, T, T);
-      typedef T (*ff12_functor)(T, T, T, T, T, T, T, T, T, T, T, T);
-      typedef T (*ff13_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T);
-      typedef T (*ff14_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T, T);
-      typedef T (*ff15_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T, T, T);
+     enum symtab_mutability_type
+     {
+       e_unknown   = 0,
+       e_mutable   = 1,
+       e_immutable = 2
+     };
+
+     typedef T (*ff00_functor)();
+     typedef T (*ff01_functor)(T);
+     typedef T (*ff02_functor)(T, T);
+     typedef T (*ff03_functor)(T, T, T);
+     typedef T (*ff04_functor)(T, T, T, T);
+     typedef T (*ff05_functor)(T, T, T, T, T);
+     typedef T (*ff06_functor)(T, T, T, T, T, T);
+     typedef T (*ff07_functor)(T, T, T, T, T, T, T);
+     typedef T (*ff08_functor)(T, T, T, T, T, T, T, T);
+     typedef T (*ff09_functor)(T, T, T, T, T, T, T, T, T);
+     typedef T (*ff10_functor)(T, T, T, T, T, T, T, T, T, T);
+     typedef T (*ff11_functor)(T, T, T, T, T, T, T, T, T, T, T);
+     typedef T (*ff12_functor)(T, T, T, T, T, T, T, T, T, T, T, T);
+     typedef T (*ff13_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T);
+     typedef T (*ff14_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T, T);
+     typedef T (*ff15_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T, T, T);
 
    protected:
 
@@ -17949,11 +17975,13 @@ namespace exprtk
          control_block()
          : ref_count(1)
          , data_(st_data::create())
+         , mutability_(e_mutable)
          {}
 
          explicit control_block(st_data* data)
          : ref_count(1)
          , data_(data)
+         , mutability_(e_mutable)
          {}
 
         ~control_block()
@@ -17989,21 +18017,29 @@ namespace exprtk
             }
          }
 
+         void set_mutability(const symtab_mutability_type mutability)
+         {
+            mutability_ = mutability;
+         }
+
          std::size_t ref_count;
          st_data* data_;
+         symtab_mutability_type mutability_;
       };
 
    public:
 
-      symbol_table()
+      symbol_table(const symtab_mutability_type mutability = e_mutable)
       : control_block_(control_block::create())
       {
+         control_block_->set_mutability(mutability);
          clear();
       }
 
      ~symbol_table()
       {
-         control_block::destroy(control_block_,this);
+         exprtk::details::dump_ptr("~symbol_table", this);
+         control_block::destroy(control_block_, this);
       }
 
       symbol_table(const symbol_table<T>& st)
@@ -18030,6 +18066,11 @@ namespace exprtk
          return (this == &st) || (control_block_ == st.control_block_);
       }
 
+      inline symtab_mutability_type mutability() const
+      {
+         return valid() ? control_block_->mutability_ : e_unknown;
+      }
+
       inline void clear_variables(const bool delete_node = true)
       {
          local_data().variable_store.clear(delete_node);
@@ -19103,6 +19144,7 @@ namespace exprtk
 
       inline expression<T>& release()
       {
+         exprtk::details::dump_ptr("expression::release", this);
          control_block::destroy(control_block_);
 
          return (*this);
@@ -19138,6 +19180,14 @@ namespace exprtk
 
       inline void register_symbol_table(symbol_table<T>& st)
       {
+         for (std::size_t i = 0; i < symbol_table_list_.size(); ++i)
+         {
+            if (&st == &symbol_table_list_[i])
+            {
+               return;
+            }
+         }
+
          symbol_table_list_.push_back(st);
       }
 
@@ -19905,6 +19955,130 @@ namespace exprtk
          parser_t& parser_;
       };
 
+      template <typename T_>
+      struct halfopen_range_policy
+      {
+         static inline bool is_within(const T_& v, const T_& begin, const T_& end)
+         {
+            assert(begin <= end);
+            return (begin <= v) && (v < end);
+         }
+
+         static inline bool is_less(const T_& v, const T_& begin)
+         {
+            return (v < begin);
+         }
+
+         static inline bool is_greater(const T_& v, const T_& end)
+         {
+            return (end <= v);
+         }
+
+         static inline bool end_inclusive()
+         {
+            return false;
+         }
+      };
+
+      template <typename T_>
+      struct closed_range_policy
+      {
+         static inline bool is_within(const T_& v, const T_& begin, const T_& end)
+         {
+            assert(begin <= end);
+            return (begin <= v) && (v <= end);
+         }
+
+         static inline bool is_less(const T_& v, const T_& begin)
+         {
+            return (v < begin);
+         }
+
+         static inline bool is_greater(const T_& v, const T_& end)
+         {
+            return (end < v);
+         }
+
+         static inline bool end_inclusive()
+         {
+            return true;
+         }
+      };
+
+      template <typename IntervalPointType,
+                typename RangePolicy = halfopen_range_policy<IntervalPointType> >
+      class interval_container_t
+      {
+      public:
+
+         typedef IntervalPointType interval_point_t;
+         typedef std::pair<interval_point_t, interval_point_t> interval_t;
+         typedef std::map<interval_point_t, interval_t> interval_map_t;
+         typedef typename interval_map_t::const_iterator interval_map_citr_t;
+
+         std::size_t size() const
+         {
+            return interval_map_.size();
+         }
+
+         void reset()
+         {
+            interval_map_.clear();
+         }
+
+         bool in_interval(const interval_point_t point, interval_t& interval) const
+         {
+            interval_map_citr_t itr = RangePolicy::end_inclusive() ?
+                                      interval_map_.lower_bound(point):
+                                      interval_map_.upper_bound(point);
+
+            for (; itr != interval_map_.end(); ++itr)
+            {
+               const interval_point_t& begin = itr->second.first;
+               const interval_point_t& end   = itr->second.second;
+
+               if (RangePolicy::is_within(point, begin, end))
+               {
+                  interval = interval_t(begin,end);
+                  return true;
+               }
+               else if (RangePolicy::is_greater(point, end))
+               {
+                  break;
+               }
+            }
+
+            return false;
+         }
+
+         bool in_interval(const interval_point_t point) const
+         {
+            interval_t interval;
+            return in_interval(point,interval);
+         }
+
+         bool add_interval(const interval_point_t begin, const interval_point_t end)
+         {
+            if ((end <= begin) || in_interval(begin) || in_interval(end))
+            {
+               return false;
+            }
+
+            interval_map_[end] = std::make_pair(begin, end);
+
+            return true;
+         }
+
+         bool add_interval(const interval_t interval)
+         {
+            return add_interval(interval.first, interval.second);
+         }
+
+      private:
+
+         interval_map_t interval_map_;
+      };
+
       class stack_limit_handler
       {
       public:
@@ -19959,6 +20133,41 @@ namespace exprtk
          typedef typename symbol_table_t::vararg_function_ptr  vararg_function_ptr;
          typedef typename symbol_table_t::generic_function_ptr generic_function_ptr;
 
+         struct variable_context
+         {
+            variable_context()
+            : symbol_table(0)
+            , variable(0)
+            {}
+
+            const symbol_table_t* symbol_table;
+            variable_ptr variable;
+         };
+
+         struct vector_context
+         {
+            vector_context()
+            : symbol_table(0)
+            , vector_holder(0)
+            {}
+
+            const symbol_table_t* symbol_table;
+            vector_holder_ptr vector_holder;
+         };
+
+         #ifndef exprtk_disable_string_capabilities
+         struct string_context
+         {
+            string_context()
+            : symbol_table(0)
+            , str_var(0)
+            {}
+
+            const symbol_table_t* symbol_table;
+            stringvar_ptr str_var;
+         };
+         #endif
+
          inline bool empty() const
          {
             return symtab_list_.empty();
@@ -19999,6 +20208,31 @@ namespace exprtk
                return false;
          }
 
+         inline variable_context get_variable_context(const std::string& variable_name) const
+         {
+            variable_context result;
+            if (!valid_symbol(variable_name))
+               return result;
+
+            for (std::size_t i = 0; i < symtab_list_.size(); ++i)
+            {
+               if (!symtab_list_[i].valid())
+               {
+                  continue;
+               }
+
+               result.variable = local_data(i)
+                                    .variable_store.get(variable_name);
+               if (result.variable)
+               {
+                  result.symbol_table = &symtab_list_[i];
+                  break;
+               }
+            }
+
+            return result;
+         }
+
          inline variable_ptr get_variable(const std::string& variable_name) const
          {
             if (!valid_symbol(variable_name))
@@ -20039,6 +20273,32 @@ namespace exprtk
          }
 
          #ifndef exprtk_disable_string_capabilities
+         inline string_context get_string_context(const std::string& string_name) const
+         {
+            string_context result;
+
+            if (!valid_symbol(string_name))
+               return result;
+
+            for (std::size_t i = 0; i < symtab_list_.size(); ++i)
+            {
+               if (!symtab_list_[i].valid())
+               {
+                  continue;
+               }
+
+               result.str_var = local_data(i).stringvar_store.get(string_name);
+
+               if (result.str_var)
+               {
+                  result.symbol_table = &symtab_list_[i];
+                  break;
+               }
+            }
+
+            return result;
+         }
+
          inline stringvar_ptr get_stringvar(const std::string& string_name) const
          {
             if (!valid_symbol(string_name))
@@ -20166,6 +20426,31 @@ namespace exprtk
             return result;
          }
 
+         inline vector_context get_vector_context(const std::string& vector_name) const
+         {
+            vector_context result;
+            if (!valid_symbol(vector_name))
+               return result;
+
+            for (std::size_t i = 0; i < symtab_list_.size(); ++i)
+            {
+               if (!symtab_list_[i].valid())
+               {
+                  continue;
+               }
+
+               result.vector_holder = local_data(i).vector_store.get(vector_name);
+
+               if (result.vector_holder)
+               {
+                  result.symbol_table = &symtab_list_[i];
+                  break;
+               }
+            }
+
+            return result;
+         }
+
          inline vector_holder_ptr get_vector(const std::string& vector_name) const
          {
             if (!valid_symbol(vector_name))
@@ -23215,6 +23500,12 @@ namespace exprtk
          return parse_base_operation();
       }
 
+      void handle_brkcnt_scope_exit()
+      {
+         assert(!brkcnt_list_.empty());
+         brkcnt_list_.pop_front();
+      }
+
       inline expression_node_ptr parse_while_loop()
       {
          // Parse: [while][(][test expr][)][{][expression][}]
@@ -23263,7 +23554,7 @@ namespace exprtk
          {
             scoped_inc_dec sid(state_.parsing_loop_stmt_count);
 
-            if (0 == (branch = parse_multi_sequence("while-loop")))
+            if (0 == (branch = parse_multi_sequence("while-loop", true)))
             {
                set_error(
                   make_error(parser_error::e_syntax,
@@ -23285,18 +23576,18 @@ namespace exprtk
             }
          }
 
+         handle_brkcnt_scope_exit();
+
          if (!result)
          {
             free_node(node_allocator_, branch     );
             free_node(node_allocator_, condition  );
             free_node(node_allocator_, result_node);
 
-            brkcnt_list_.pop_front();
-
             return error_node();
          }
-         else
-            return result_node;
+
+         return result_node;
       }
 
       inline expression_node_ptr parse_repeat_until_loop()
@@ -23375,8 +23666,6 @@ namespace exprtk
 
             if (sdd.delete_ptr)
             {
-               brkcnt_list_.pop_front();
-
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
@@ -23389,8 +23678,6 @@ namespace exprtk
 
          if (!token_is(token_t::e_lbracket))
          {
-            brkcnt_list_.pop_front();
-
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
@@ -23398,13 +23685,10 @@ namespace exprtk
                           exprtk_error_location));
 
             free_node(node_allocator_,branch);
-
             return error_node();
          }
          else if (0 == (condition = parse_expression()))
          {
-            brkcnt_list_.pop_front();
-
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
@@ -23412,7 +23696,6 @@ namespace exprtk
                           exprtk_error_location));
 
             free_node(node_allocator_,branch);
-
             return error_node();
          }
          else if (!token_is(token_t::e_rbracket))
@@ -23426,8 +23709,6 @@ namespace exprtk
             free_node(node_allocator_, branch   );
             free_node(node_allocator_, condition);
 
-            brkcnt_list_.pop_front();
-
             return error_node();
          }
 
@@ -23446,15 +23727,12 @@ namespace exprtk
 
             free_node(node_allocator_,condition);
 
-            brkcnt_list_.pop_front();
-
             return error_node();
          }
-         else
-         {
-            brkcnt_list_.pop_front();
-            return result;
-         }
+
+         handle_brkcnt_scope_exit();
+
+         return result;
       }
 
       inline expression_node_ptr parse_for_loop()
@@ -23646,7 +23924,7 @@ namespace exprtk
 
             scoped_inc_dec sid(state_.parsing_loop_stmt_count);
 
-            if (0 == (loop_body = parse_multi_sequence("for-loop")))
+            if (0 == (loop_body = parse_multi_sequence("for-loop", true)))
             {
                set_error(
                   make_error(parser_error::e_syntax,
@@ -23669,26 +23947,18 @@ namespace exprtk
             free_node(node_allocator_, condition  );
             free_node(node_allocator_, incrementor);
             free_node(node_allocator_, loop_body  );
-
-            if (!brkcnt_list_.empty())
-            {
-               brkcnt_list_.pop_front();
-            }
-
             return error_node();
          }
-         else
-         {
-            expression_node_ptr result_node =
-               expression_generator_.for_loop(initialiser,
-                                              condition,
-                                              incrementor,
-                                              loop_body,
-                                              brkcnt_list_.front());
-            brkcnt_list_.pop_front();
 
-            return result_node;
-         }
+         expression_node_ptr result_node =
+            expression_generator_.for_loop(initialiser,
+                                           condition,
+                                           incrementor,
+                                           loop_body,
+                                           brkcnt_list_.front());
+         handle_brkcnt_scope_exit();
+
+         return result_node;
       }
 
       inline expression_node_ptr parse_switch_statement()
@@ -23998,7 +24268,7 @@ namespace exprtk
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR096 - Unsupported vararg function: " + symbol,
+                          "ERR096 - Unsupported built-in vararg function: " + symbol,
                           exprtk_error_location));
 
             return error_node();
@@ -24021,6 +24291,18 @@ namespace exprtk
             return error_node();
          }
 
+         if (token_is(token_t::e_rbracket))
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR098 - vararg function: " + symbol +
+                          " requires at least one input parameter",
+                          exprtk_error_location));
+
+            return error_node();
+         }
+
          for ( ; ; )
          {
             expression_node_ptr arg = parse_expression();
@@ -24037,7 +24319,7 @@ namespace exprtk
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR098 - Expected ',' for call to vararg function: " + symbol,
+                             "ERR099 - Expected ',' for call to vararg function: " + symbol,
                              exprtk_error_location));
 
                return error_node();
@@ -24058,7 +24340,7 @@ namespace exprtk
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR099 - Expected '[' as start of string range definition",
+                          "ERR100 - Expected '[' as start of string range definition",
                           exprtk_error_location));
 
             free_node(node_allocator_,expression);
@@ -24086,7 +24368,7 @@ namespace exprtk
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR100 - Failed to generate string range node",
+                          "ERR101 - Failed to generate string range node",
                           exprtk_error_location));
 
             free_node(node_allocator_,expression);
@@ -24206,15 +24488,18 @@ namespace exprtk
             return expression_generator_.vararg_function(details::e_multi,expression_list);
       }
 
-      inline expression_node_ptr parse_multi_sequence(const std::string& source = "")
+      inline expression_node_ptr parse_multi_sequence(const std::string& source = "",
+                                                      const bool enforce_crlbrackets = false)
       {
+         token_t::token_type open_bracket  = token_t::e_lcrlbracket;
          token_t::token_type close_bracket = token_t::e_rcrlbracket;
          token_t::token_type seperator     = token_t::e_eof;
 
-         if (!token_is(token_t::e_lcrlbracket))
+         if (!token_is(open_bracket))
          {
-            if (token_is(token_t::e_lbracket))
+            if (!enforce_crlbrackets && token_is(token_t::e_lbracket))
             {
+               open_bracket  = token_t::e_lbracket;
                close_bracket = token_t::e_rbracket;
                seperator     = token_t::e_comma;
             }
@@ -24223,14 +24508,14 @@ namespace exprtk
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR101 - Expected '" + token_t::to_str(close_bracket) + "' for call to multi-sequence" +
+                             "ERR102 - Expected '" + token_t::to_str(open_bracket) + "' for call to multi-sequence" +
                              ((!source.empty()) ? std::string(" section of " + source): ""),
                              exprtk_error_location));
 
                return error_node();
             }
          }
-         else if (token_is(token_t::e_rcrlbracket))
+         else if (token_is(close_bracket))
          {
             return node_allocator_.allocate<details::null_node<T> >();
          }
@@ -24270,7 +24555,7 @@ namespace exprtk
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR102 - Expected '" + details::to_str(seperator) + "' for call to multi-sequence section of " + source,
+                             "ERR103 - Expected '" + details::to_str(seperator) + "' for call to multi-sequence section of " + source,
                              exprtk_error_location));
 
                return error_node();
@@ -24280,7 +24565,7 @@ namespace exprtk
                break;
          }
 
-         result = simplify(arg_list,side_effect_list,source.empty());
+         result = simplify(arg_list, side_effect_list, source.empty());
 
          sdd.delete_ptr = (0 == result);
          return result;
@@ -24304,7 +24589,7 @@ namespace exprtk
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR103 - Expected '[' for start of range",
+                          "ERR104 - Expected '[' for start of range",
                           exprtk_error_location));
 
             return false;
@@ -24325,7 +24610,7 @@ namespace exprtk
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR104 - Failed parse begin section of range",
+                             "ERR105 - Failed parse begin section of range",
                              exprtk_error_location));
 
                return false;
@@ -24348,7 +24633,7 @@ namespace exprtk
                   set_error(
                      make_error(parser_error::e_syntax,
                                 current_token(),
-                                "ERR105 - Range lower bound less than zero! Constraint: r0 >= 0",
+                                "ERR106 - Range lower bound less than zero! Constraint: r0 >= 0",
                                 exprtk_error_location));
 
                   return false;
@@ -24365,7 +24650,7 @@ namespace exprtk
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR106 - Expected ':' for break  in range",
+                             "ERR107 - Expected ':' for break  in range",
                              exprtk_error_location));
 
                rp.free();
@@ -24388,7 +24673,7 @@ namespace exprtk
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR107 - Failed parse end section of range",
+                             "ERR108 - Failed parse end section of range",
                              exprtk_error_location));
 
                rp.free();
@@ -24413,7 +24698,7 @@ namespace exprtk
                   set_error(
                      make_error(parser_error::e_syntax,
                                 current_token(),
-                                "ERR108 - Range upper bound less than zero! Constraint: r1 >= 0",
+                                "ERR109 - Range upper bound less than zero! Constraint: r1 >= 0",
                                 exprtk_error_location));
 
                   rp.free();
@@ -24432,7 +24717,7 @@ namespace exprtk
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR109 - Expected ']' for start of range",
+                             "ERR110 - Expected ']' for start of range",
                              exprtk_error_location));
 
                rp.free();
@@ -24460,7 +24745,7 @@ namespace exprtk
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR110 - Invalid range, Constraint: r0 <= r1",
+                             "ERR111 - Invalid range, Constraint: r0 <= r1",
                              exprtk_error_location));
 
                return false;
@@ -24496,24 +24781,36 @@ namespace exprtk
          }
          else
          {
-            if (!symtab_store_.is_conststr_stringvar(symbol))
+            typedef typename symtab_store::string_context str_ctxt_t;
+            str_ctxt_t str_ctx = symtab_store_.get_string_context(symbol);
+
+            if ((0 == str_ctx.str_var) || !symtab_store_.is_conststr_stringvar(symbol))
             {
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR111 - Unknown string symbol",
+                             "ERR112 - Unknown string symbol",
                              exprtk_error_location));
 
                return error_node();
             }
 
-            result = symtab_store_.get_stringvar(symbol);
+            assert(str_ctx.str_var != 0);
+            assert(str_ctx.symbol_table != 0);
+
+            result = str_ctx.str_var;
 
             if (symtab_store_.is_constant_string(symbol))
             {
                const_str_node = static_cast<strvar_node_t>(result);
                result = expression_generator_(const_str_node->str());
             }
+            else if (symbol_table_t::e_immutable == str_ctx.symbol_table->mutability())
+            {
+               lodge_immutable_symbol(
+                  current_token(),
+                  make_memory_range(str_ctx.str_var->base(), str_ctx.str_var->size()));
+            }
 
             lodge_symbol(symbol, e_st_string);
          }
@@ -24616,7 +24913,7 @@ namespace exprtk
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR112 - Overflow in range for string: '" + const_str + "'[" +
+                             "ERR113 - Overflow in range for string: '" + const_str + "'[" +
                              (rp.n0_c.first ? details::to_str(static_cast<int>(rp.n0_c.second)) : "?") + ":" +
                              (rp.n1_c.first ? details::to_str(static_cast<int>(rp.n1_c.second)) : "?") + "]",
                              exprtk_error_location));
@@ -24657,20 +24954,37 @@ namespace exprtk
               (scope_element::e_vector != se.type)
             )
          {
-            if (0 == (vec = symtab_store_.get_vector(symbol)))
+            typedef typename symtab_store::vector_context vec_ctxt_t;
+            vec_ctxt_t vec_ctx = symtab_store_.get_vector_context(symbol);
+
+            if (0 == vec_ctx.vector_holder)
             {
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR113 - Symbol '" + symbol+ " not a vector",
+                             "ERR114 - Symbol '" + symbol+ " not a vector",
                              exprtk_error_location));
 
                return error_node();
             }
+
+            assert(0 != vec_ctx.vector_holder);
+            assert(0 != vec_ctx.symbol_table );
+
+            vec = vec_ctx.vector_holder;
+
+            if (symbol_table_t::e_immutable == vec_ctx.symbol_table->mutability())
+            {
+               lodge_immutable_symbol(
+                  current_token(),
+                  make_memory_range(vec->data(), vec->size()));
+            }
          }
          else
             vec = se.vec_node;
 
+         assert(0 != vec);
+
          expression_node_ptr index_expr = error_node();
 
          next_token();
@@ -24688,7 +25002,7 @@ namespace exprtk
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR114 - Failed to parse index for vector: '" + symbol + "'",
+                          "ERR115 - Failed to parse index for vector: '" + symbol + "'",
                           exprtk_error_location));
 
             return error_node();
@@ -24698,7 +25012,7 @@ namespace exprtk
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR115 - Expected ']' for index of vector: '" + symbol + "'",
+                          "ERR116 - Expected ']' for index of vector: '" + symbol + "'",
                           exprtk_error_location));
 
             free_node(node_allocator_,index_expr);
@@ -24717,7 +25031,7 @@ namespace exprtk
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR116 - Index of " + details::to_str(index) + " out of range for "
+                             "ERR117 - Index of " + details::to_str(index) + " out of range for "
                              "vector '" + symbol + "' of size " + details::to_str(vec_size),
                              exprtk_error_location));
 
@@ -24749,7 +25063,7 @@ namespace exprtk
                   set_error(
                      make_error(parser_error::e_syntax,
                                 current_token(),
-                                "ERR117 - Zero parameter call to vararg function: "
+                                "ERR118 - Zero parameter call to vararg function: "
                                 + vararg_function_name + " not allowed",
                                 exprtk_error_location));
 
@@ -24774,7 +25088,7 @@ namespace exprtk
                      set_error(
                         make_error(parser_error::e_syntax,
                                    current_token(),
-                                   "ERR118 - Expected ',' for call to vararg function: "
+                                   "ERR119 - Expected ',' for call to vararg function: "
                                    + vararg_function_name,
                                    exprtk_error_location));
 
@@ -24788,7 +25102,7 @@ namespace exprtk
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR119 - Zero parameter call to vararg function: "
+                          "ERR120 - Zero parameter call to vararg function: "
                           + vararg_function_name + " not allowed",
                           exprtk_error_location));
 
@@ -24800,7 +25114,7 @@ namespace exprtk
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR120 - Invalid number of parameters to call to vararg function: "
+                          "ERR121 - Invalid number of parameters to call to vararg function: "
                           + vararg_function_name + ", require at least "
                           + details::to_str(static_cast<int>(vararg_function->min_num_args())) + " parameters",
                           exprtk_error_location));
@@ -24812,7 +25126,7 @@ namespace exprtk
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR121 - Invalid number of parameters to call to vararg function: "
+                          "ERR122 - Invalid number of parameters to call to vararg function: "
                           + vararg_function_name + ", require no more than "
                           + details::to_str(static_cast<int>(vararg_function->max_num_args())) + " parameters",
                           exprtk_error_location));
@@ -24890,7 +25204,7 @@ namespace exprtk
                   set_error(
                      make_error(parser_error::e_syntax,
                                 parser_.current_token(),
-                                "ERR122 - Failed parameter type check for function '" + function_name_ + "', "
+                                "ERR123 - Failed parameter type check for function '" + function_name_ + "', "
                                 "Expected '" + function_definition_list_[0].param_seq +
                                 "' call set: '" + param_seq + "'",
                                 exprtk_error_location));
@@ -24912,7 +25226,7 @@ namespace exprtk
                   set_error(
                      make_error(parser_error::e_syntax,
                                 parser_.current_token(),
-                                "ERR123 - Failed parameter type check for function '" + function_name_ + "', "
+                                "ERR124 - Failed parameter type check for function '" + function_name_ + "', "
                                 "Best match: '" + function_definition_list_[max_diff_index].param_seq +
                                 "' call set: '" + param_seq + "'",
                                 exprtk_error_location));
@@ -25054,7 +25368,7 @@ namespace exprtk
                      set_error(
                         make_error(parser_error::e_syntax,
                                    parser_.current_token(),
-                                   "ERR124 - Invalid parameter sequence of '" + param_seq_list[i] +
+                                   "ERR125 - Invalid parameter sequence of '" + param_seq_list[i] +
                                    "' for function: " + function_name_,
                                    exprtk_error_location));
                   return;
@@ -25070,7 +25384,7 @@ namespace exprtk
                      set_error(
                         make_error(parser_error::e_syntax,
                                    parser_.current_token(),
-                                   "ERR125 - Function '" + function_name_ + "' has a parameter sequence conflict between " +
+                                   "ERR126 - Function '" + function_name_ + "' has a parameter sequence conflict between " +
                                    "pseq_idx[" + details::to_str(seq_itr->second) + "] and" +
                                    "pseq_idx[" + details::to_str(i) + "] " +
                                    "param seq: " + param_seq_list[i],
@@ -25102,14 +25416,18 @@ namespace exprtk
 
          std::string param_type_list;
 
-         type_checker tc((*this), function_name, function->parameter_sequence, type_checker::e_string);
+         type_checker tc(
+            (*this),
+            function_name,
+            function->parameter_sequence,
+            type_checker::e_string);
 
          if (tc.invalid())
          {
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR126 - Type checker instantiation failure for generic function: " + function_name,
+                          "ERR127 - Type checker instantiation failure for generic function: " + function_name,
                           exprtk_error_location));
 
             return error_node();
@@ -25127,7 +25445,7 @@ namespace exprtk
                   set_error(
                      make_error(parser_error::e_syntax,
                                 current_token(),
-                                "ERR127 - Zero parameter call to generic function: "
+                                "ERR128 - Zero parameter call to generic function: "
                                 + function_name + " not allowed",
                                 exprtk_error_location));
 
@@ -25159,7 +25477,7 @@ namespace exprtk
                      set_error(
                         make_error(parser_error::e_syntax,
                                    current_token(),
-                                   "ERR128 - Expected ',' for call to generic function: " + function_name,
+                                   "ERR129 - Expected ',' for call to generic function: " + function_name,
                                    exprtk_error_location));
 
                      return error_node();
@@ -25176,7 +25494,7 @@ namespace exprtk
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR129 - Zero parameter call to generic function: "
+                          "ERR130 - Zero parameter call to generic function: "
                           + function_name + " not allowed",
                           exprtk_error_location));
 
@@ -25193,7 +25511,7 @@ namespace exprtk
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR130 - Invalid input parameter sequence for call to generic function: " + function_name,
+                          "ERR131 - Invalid input parameter sequence for call to generic function: " + function_name,
                           exprtk_error_location));
 
             return error_node();
@@ -25231,7 +25549,7 @@ namespace exprtk
                   set_error(
                      make_error(parser_error::e_syntax,
                                 current_token(),
-                                "ERR131 - Zero parameter call to generic function: "
+                                "ERR132 - Zero parameter call to generic function: "
                                 + function_name + " not allowed",
                                 exprtk_error_location));
 
@@ -25263,7 +25581,7 @@ namespace exprtk
                      set_error(
                         make_error(parser_error::e_syntax,
                                    current_token(),
-                                   "ERR132 - Expected ',' for call to string function: " + function_name,
+                                   "ERR133 - Expected ',' for call to string function: " + function_name,
                                    exprtk_error_location));
 
                      return false;
@@ -25310,7 +25628,7 @@ namespace exprtk
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR133 - Invalid input parameter sequence for call to string function: " + function_name,
+                          "ERR134 - Invalid input parameter sequence for call to string function: " + function_name,
                           exprtk_error_location));
 
             return error_node();
@@ -25362,7 +25680,7 @@ namespace exprtk
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR134 - Invalid input parameter sequence for call to overloaded function: " + function_name,
+                          "ERR135 - Invalid input parameter sequence for call to overloaded function: " + function_name,
                           exprtk_error_location));
 
             return error_node();
@@ -25393,7 +25711,7 @@ namespace exprtk
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR135 - Invalid return type for call to overloaded function: " + function_name,
+                          "ERR136 - Invalid return type for call to overloaded function: " + function_name,
                           exprtk_error_location));
          }
 
@@ -25421,7 +25739,7 @@ namespace exprtk
                p.set_error(
                     make_error(parser_error::e_syntax,
                                p.current_token(),
-                               "ERR136 - Expected '(' for special function '" + sf_name + "'",
+                               "ERR137 - Expected '(' for special function '" + sf_name + "'",
                                exprtk_error_location));
 
                return error_node();
@@ -25442,7 +25760,7 @@ namespace exprtk
                      p.set_error(
                           make_error(parser_error::e_syntax,
                                      p.current_token(),
-                                     "ERR137 - Expected ',' before next parameter of special function '" + sf_name + "'",
+                                     "ERR138 - Expected ',' before next parameter of special function '" + sf_name + "'",
                                      exprtk_error_location));
 
                      return p.error_node();
@@ -25455,7 +25773,7 @@ namespace exprtk
                p.set_error(
                     make_error(parser_error::e_syntax,
                                p.current_token(),
-                               "ERR138 - Invalid number of parameters for special function '" + sf_name + "'",
+                               "ERR139 - Invalid number of parameters for special function '" + sf_name + "'",
                                exprtk_error_location));
 
                return p.error_node();
@@ -25482,7 +25800,7 @@ namespace exprtk
             set_error(
                make_error(parser_error::e_token,
                           current_token(),
-                          "ERR139 - Invalid special function[1]: " + sf_name,
+                          "ERR140 - Invalid special function[1]: " + sf_name,
                           exprtk_error_location));
 
             return error_node();
@@ -25496,7 +25814,7 @@ namespace exprtk
             set_error(
                make_error(parser_error::e_token,
                           current_token(),
-                          "ERR140 - Invalid special function[2]: " + sf_name,
+                          "ERR141 - Invalid special function[2]: " + sf_name,
                           exprtk_error_location));
 
             return error_node();
@@ -25528,7 +25846,7 @@ namespace exprtk
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR141 - Invoking 'break' within a break call is not allowed",
+                          "ERR142 - Invoking 'break' within a break call is not allowed",
                           exprtk_error_location));
 
             return error_node();
@@ -25538,7 +25856,7 @@ namespace exprtk
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR142 - Invalid use of 'break', allowed only in the scope of a loop",
+                          "ERR143 - Invalid use of 'break', allowed only in the scope of a loop",
                           exprtk_error_location));
 
             return error_node();
@@ -25561,7 +25879,7 @@ namespace exprtk
                   set_error(
                      make_error(parser_error::e_syntax,
                                 current_token(),
-                                "ERR143 - Failed to parse return expression for 'break' statement",
+                                "ERR144 - Failed to parse return expression for 'break' statement",
                                 exprtk_error_location));
 
                   return error_node();
@@ -25571,7 +25889,7 @@ namespace exprtk
                   set_error(
                      make_error(parser_error::e_syntax,
                                 current_token(),
-                                "ERR144 - Expected ']' at the completion of break's return expression",
+                                "ERR145 - Expected ']' at the completion of break's return expression",
                                 exprtk_error_location));
 
                   free_node(node_allocator_,return_expr);
@@ -25589,7 +25907,7 @@ namespace exprtk
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR145 - Invalid use of 'break', allowed only in the scope of a loop",
+                          "ERR146 - Invalid use of 'break', allowed only in the scope of a loop",
                           exprtk_error_location));
          }
 
@@ -25603,7 +25921,7 @@ namespace exprtk
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR146 - Invalid use of 'continue', allowed only in the scope of a loop",
+                          "ERR147 - Invalid use of 'continue', allowed only in the scope of a loop",
                           exprtk_error_location));
 
             return error_node();
@@ -25629,7 +25947,7 @@ namespace exprtk
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR147 - Expected '[' as part of vector size definition",
+                          "ERR148 - Expected '[' as part of vector size definition",
                           exprtk_error_location));
 
             return error_node();
@@ -25639,7 +25957,7 @@ namespace exprtk
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR148 - Failed to determine size of vector '" + vec_name + "'",
+                          "ERR149 - Failed to determine size of vector '" + vec_name + "'",
                           exprtk_error_location));
 
             return error_node();
@@ -25651,7 +25969,7 @@ namespace exprtk
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR149 - Expected a literal number as size of vector '" + vec_name + "'",
+                          "ERR150 - Expected a literal number as size of vector '" + vec_name + "'",
                           exprtk_error_location));
 
             return error_node();
@@ -25673,7 +25991,7 @@ namespace exprtk
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR150 - Invalid vector size. Must be an integer in the range [0,2e9], size: " +
+                          "ERR151 - Invalid vector size. Must be an integer in the range [0,2e9], size: " +
                           details::to_str(details::numeric::to_int32(vector_size)),
                           exprtk_error_location));
 
@@ -25693,7 +26011,7 @@ namespace exprtk
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR151 - Expected ']' as part of vector size definition",
+                          "ERR152 - Expected ']' as part of vector size definition",
                           exprtk_error_location));
 
             return error_node();
@@ -25705,7 +26023,7 @@ namespace exprtk
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR152 - Expected ':=' as part of vector definition",
+                             "ERR153 - Expected ':=' as part of vector definition",
                              exprtk_error_location));
 
                return error_node();
@@ -25719,7 +26037,7 @@ namespace exprtk
                   set_error(
                      make_error(parser_error::e_syntax,
                                 current_token(),
-                                "ERR153 - Failed to parse single vector initialiser",
+                                "ERR154 - Failed to parse single vector initialiser",
                                 exprtk_error_location));
 
                   return error_node();
@@ -25732,7 +26050,7 @@ namespace exprtk
                   set_error(
                      make_error(parser_error::e_syntax,
                                 current_token(),
-                                "ERR154 - Expected ']' to close single value vector initialiser",
+                                "ERR155 - Expected ']' to close single value vector initialiser",
                                 exprtk_error_location));
 
                   return error_node();
@@ -25779,7 +26097,7 @@ namespace exprtk
                      set_error(
                         make_error(parser_error::e_syntax,
                                    current_token(),
-                                   "ERR155 - Expected '{' as part of vector initialiser list",
+                                   "ERR156 - Expected '{' as part of vector initialiser list",
                                    exprtk_error_location));
 
                      return error_node();
@@ -25799,7 +26117,7 @@ namespace exprtk
                      set_error(
                         make_error(parser_error::e_syntax,
                                    current_token(),
-                                   "ERR156 - Expected '{' as part of vector initialiser list",
+                                   "ERR157 - Expected '{' as part of vector initialiser list",
                                    exprtk_error_location));
 
                      return error_node();
@@ -25817,7 +26135,7 @@ namespace exprtk
                      set_error(
                         make_error(parser_error::e_syntax,
                                    current_token(),
-                                   "ERR157 - Expected ',' between vector initialisers",
+                                   "ERR158 - Expected ',' between vector initialisers",
                                    exprtk_error_location));
 
                      return error_node();
@@ -25839,19 +26157,19 @@ namespace exprtk
                   set_error(
                      make_error(parser_error::e_syntax,
                                 current_token(),
-                                "ERR158 - Expected ';' at end of vector definition",
+                                "ERR159 - Expected ';' at end of vector definition",
                                 exprtk_error_location));
 
                   return error_node();
                }
             }
 
-            if (vec_initilizer_list.size() > vector_size)
+            if (T(vec_initilizer_list.size()) > vector_size)
             {
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR159 - Initialiser list larger than the number of elements in the vector: '" + vec_name + "'",
+                             "ERR160 - Initialiser list larger than the number of elements in the vector: '" + vec_name + "'",
                              exprtk_error_location));
 
                return error_node();
@@ -25871,7 +26189,7 @@ namespace exprtk
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR160 - Illegal redefinition of local vector: '" + vec_name + "'",
+                             "ERR161 - Illegal redefinition of local vector: '" + vec_name + "'",
                              exprtk_error_location));
 
                return error_node();
@@ -25905,7 +26223,7 @@ namespace exprtk
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR161 - Failed to add new local vector '" + vec_name + "' to SEM",
+                             "ERR162 - Failed to add new local vector '" + vec_name + "' to SEM",
                              exprtk_error_location));
 
                sem_.free_element(nse);
@@ -25964,7 +26282,7 @@ namespace exprtk
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR162 - Illegal redefinition of local variable: '" + str_name + "'",
+                             "ERR163 - Illegal redefinition of local variable: '" + str_name + "'",
                              exprtk_error_location));
 
                free_node(node_allocator_,initialisation_expression);
@@ -25996,7 +26314,7 @@ namespace exprtk
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR163 - Failed to add new local string variable '" + str_name + "' to SEM",
+                             "ERR164 - Failed to add new local string variable '" + str_name + "' to SEM",
                              exprtk_error_location));
 
                free_node(node_allocator_,initialisation_expression);
@@ -26042,7 +26360,7 @@ namespace exprtk
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR164 - Illegal variable definition",
+                          "ERR165 - Illegal variable definition",
                           exprtk_error_location));
 
             return error_node();
@@ -26063,7 +26381,7 @@ namespace exprtk
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR165 - Expected a symbol for variable definition",
+                          "ERR166 - Expected a symbol for variable definition",
                           exprtk_error_location));
 
             return error_node();
@@ -26073,7 +26391,7 @@ namespace exprtk
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR166 - Illegal redefinition of reserved keyword: '" + var_name + "'",
+                          "ERR167 - Illegal redefinition of reserved keyword: '" + var_name + "'",
                           exprtk_error_location));
 
             return error_node();
@@ -26083,7 +26401,7 @@ namespace exprtk
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR167 - Illegal redefinition of variable '" + var_name + "'",
+                          "ERR168 - Illegal redefinition of variable '" + var_name + "'",
                           exprtk_error_location));
 
             return error_node();
@@ -26093,7 +26411,7 @@ namespace exprtk
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR168 - Illegal redefinition of local variable: '" + var_name + "'",
+                          "ERR169 - Illegal redefinition of local variable: '" + var_name + "'",
                           exprtk_error_location));
 
             return error_node();
@@ -26113,7 +26431,7 @@ namespace exprtk
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR169 - Failed to parse initialisation expression",
+                             "ERR170 - Failed to parse initialisation expression",
                              exprtk_error_location));
 
                return error_node();
@@ -26131,7 +26449,7 @@ namespace exprtk
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR170 - Expected ';' after variable definition",
+                             "ERR171 - Expected ';' after variable definition",
                              exprtk_error_location));
 
                free_node(node_allocator_,initialisation_expression);
@@ -26159,7 +26477,7 @@ namespace exprtk
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR171 - Illegal redefinition of local variable: '" + var_name + "'",
+                             "ERR172 - Illegal redefinition of local variable: '" + var_name + "'",
                              exprtk_error_location));
 
                free_node(node_allocator_, initialisation_expression);
@@ -26191,7 +26509,7 @@ namespace exprtk
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR172 - Failed to add new local variable '" + var_name + "' to SEM",
+                             "ERR173 - Failed to add new local variable '" + var_name + "' to SEM",
                              exprtk_error_location));
 
                free_node(node_allocator_, initialisation_expression);
@@ -26228,7 +26546,7 @@ namespace exprtk
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR173 - Expected a '{}' for uninitialised var definition",
+                          "ERR174 - Expected a '{}' for uninitialised var definition",
                           exprtk_error_location));
 
             return error_node();
@@ -26238,7 +26556,7 @@ namespace exprtk
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR174 - Expected ';' after uninitialised variable definition",
+                          "ERR175 - Expected ';' after uninitialised variable definition",
                           exprtk_error_location));
 
             return error_node();
@@ -26255,7 +26573,7 @@ namespace exprtk
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR175 - Illegal redefinition of local variable: '" + var_name + "'",
+                             "ERR176 - Illegal redefinition of local variable: '" + var_name + "'",
                              exprtk_error_location));
 
                return error_node();
@@ -26285,7 +26603,7 @@ namespace exprtk
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR176 - Failed to add new local variable '" + var_name + "' to SEM",
+                             "ERR177 - Failed to add new local variable '" + var_name + "' to SEM",
                              exprtk_error_location));
 
                sem_.free_element(nse);
@@ -26318,7 +26636,7 @@ namespace exprtk
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR177 - Expected '(' at start of swap statement",
+                          "ERR178 - Expected '(' at start of swap statement",
                           exprtk_error_location));
 
             return error_node();
@@ -26337,7 +26655,7 @@ namespace exprtk
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR178 - Expected a symbol for variable or vector element definition",
+                          "ERR179 - Expected a symbol for variable or vector element definition",
                           exprtk_error_location));
 
             return error_node();
@@ -26349,7 +26667,7 @@ namespace exprtk
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR179 - First parameter to swap is an invalid vector element: '" + var0_name + "'",
+                             "ERR180 - First parameter to swap is an invalid vector element: '" + var0_name + "'",
                              exprtk_error_location));
 
                return error_node();
@@ -26382,7 +26700,7 @@ namespace exprtk
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR180 - First parameter to swap is an invalid variable: '" + var0_name + "'",
+                             "ERR181 - First parameter to swap is an invalid variable: '" + var0_name + "'",
                              exprtk_error_location));
 
                return error_node();
@@ -26396,7 +26714,7 @@ namespace exprtk
             set_error(
                 make_error(parser_error::e_syntax,
                            current_token(),
-                           "ERR181 - Expected ',' between parameters to swap",
+                           "ERR182 - Expected ',' between parameters to swap",
                            exprtk_error_location));
 
             if (variable0_generated)
@@ -26414,7 +26732,7 @@ namespace exprtk
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR182 - Expected a symbol for variable or vector element definition",
+                          "ERR183 - Expected a symbol for variable or vector element definition",
                           exprtk_error_location));
 
             if (variable0_generated)
@@ -26431,7 +26749,7 @@ namespace exprtk
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR183 - Second parameter to swap is an invalid vector element: '" + var1_name + "'",
+                             "ERR184 - Second parameter to swap is an invalid vector element: '" + var1_name + "'",
                              exprtk_error_location));
 
                if (variable0_generated)
@@ -26469,7 +26787,7 @@ namespace exprtk
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR184 - Second parameter to swap is an invalid variable: '" + var1_name + "'",
+                             "ERR185 - Second parameter to swap is an invalid variable: '" + var1_name + "'",
                              exprtk_error_location));
 
                if (variable0_generated)
@@ -26488,7 +26806,7 @@ namespace exprtk
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR185 - Expected ')' at end of swap statement",
+                          "ERR186 - Expected ')' at end of swap statement",
                           exprtk_error_location));
 
             if (variable0_generated)
@@ -26545,7 +26863,7 @@ namespace exprtk
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR186 - Return call within a return call is not allowed",
+                          "ERR187 - Return call within a return call is not allowed",
                           exprtk_error_location));
 
             return error_node();
@@ -26569,7 +26887,7 @@ namespace exprtk
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR187 - Expected '[' at start of return statement",
+                          "ERR188 - Expected '[' at start of return statement",
                           exprtk_error_location));
 
             return error_node();
@@ -26592,7 +26910,7 @@ namespace exprtk
                   set_error(
                      make_error(parser_error::e_syntax,
                                 current_token(),
-                                "ERR188 - Expected ',' between values during call to return",
+                                "ERR189 - Expected ',' between values during call to return",
                                 exprtk_error_location));
 
                   return error_node();
@@ -26604,7 +26922,7 @@ namespace exprtk
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR189 - Zero parameter return statement not allowed",
+                          "ERR190 - Zero parameter return statement not allowed",
                           exprtk_error_location));
 
             return error_node();
@@ -26619,7 +26937,7 @@ namespace exprtk
                set_error(
                   make_error(parser_error::e_syntax,
                              prev_token,
-                             "ERR190 - Invalid ']' found during return call",
+                             "ERR191 - Invalid ']' found during return call",
                              exprtk_error_location));
 
                return error_node();
@@ -26672,7 +26990,7 @@ namespace exprtk
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR191 - Invalid sequence of variable '"+ symbol + "' and bracket",
+                             "ERR192 - Invalid sequence of variable '" + symbol + "' and bracket",
                              exprtk_error_location));
 
                return false;
@@ -26720,7 +27038,7 @@ namespace exprtk
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR192 - Invalid sequence of brackets",
+                             "ERR193 - Invalid sequence of brackets",
                              exprtk_error_location));
 
                return false;
@@ -26736,27 +27054,65 @@ namespace exprtk
          return true;
       }
 
+      typedef typename interval_container_t<const void*>::interval_t interval_t;
+      typedef interval_container_t<const void*> immutable_memory_map_t;
+      typedef std::map<interval_t,token_t> immutable_symtok_map_t;
+
+      inline interval_t make_memory_range(const T& t)
+      {
+         const T* begin = reinterpret_cast<const T*>(&t);
+         const T* end   = begin + 1;
+         return interval_t(begin, end);
+      }
+
+      inline interval_t make_memory_range(const T* begin, const std::size_t size)
+      {
+         return interval_t(begin, begin + size);
+      }
+
+      inline interval_t make_memory_range(details::char_cptr begin, const std::size_t size)
+      {
+         return interval_t(begin, begin + size);
+      }
+
+      void lodge_immutable_symbol(const lexer::token& token, const interval_t interval)
+      {
+         immutable_memory_map_.add_interval(interval);
+         immutable_symtok_map_[interval] = token;
+      }
+
       inline expression_node_ptr parse_symtab_symbol()
       {
          const std::string symbol = current_token().value;
 
          // Are we dealing with a variable or a special constant?
-         expression_node_ptr variable = symtab_store_.get_variable(symbol);
+         typedef typename symtab_store::variable_context var_ctxt_t;
+         var_ctxt_t var_ctx = symtab_store_.get_variable_context(symbol);
 
-         if (variable)
+         if (var_ctx.variable)
          {
+            assert(var_ctx.symbol_table);
+
+            expression_node_ptr result_variable = var_ctx.variable;
+
             if (symtab_store_.is_constant_node(symbol))
             {
-               variable = expression_generator_(variable->value());
+               result_variable = expression_generator_(var_ctx.variable->value());
+            }
+            else if (symbol_table_t::e_immutable == var_ctx.symbol_table->mutability())
+            {
+               lodge_immutable_symbol(current_token(), make_memory_range(var_ctx.variable->ref()));
+               result_variable = var_ctx.variable;
             }
 
             if (!post_variable_process(symbol))
                return error_node();
 
             lodge_symbol(symbol, e_st_variable);
+
             next_token();
 
-            return variable;
+            return result_variable;
          }
 
          // Are we dealing with a locally defined variable, vector or string?
@@ -26817,7 +27173,7 @@ namespace exprtk
                   set_error(
                      make_error(parser_error::e_syntax,
                                 current_token(),
-                                "ERR193 - Failed to generate node for function: '" + symbol + "'",
+                                "ERR194 - Failed to generate node for function: '" + symbol + "'",
                                 exprtk_error_location));
 
                   return error_node();
@@ -26843,7 +27199,7 @@ namespace exprtk
                   set_error(
                      make_error(parser_error::e_syntax,
                                 current_token(),
-                                "ERR194 - Failed to generate node for vararg function: '" + symbol + "'",
+                                "ERR195 - Failed to generate node for vararg function: '" + symbol + "'",
                                 exprtk_error_location));
 
                   return error_node();
@@ -26869,7 +27225,7 @@ namespace exprtk
                   set_error(
                      make_error(parser_error::e_syntax,
                                 current_token(),
-                                "ERR195 - Failed to generate node for generic function: '" + symbol + "'",
+                                "ERR196 - Failed to generate node for generic function: '" + symbol + "'",
                                 exprtk_error_location));
 
                   return error_node();
@@ -26896,7 +27252,7 @@ namespace exprtk
                   set_error(
                      make_error(parser_error::e_syntax,
                                 current_token(),
-                                "ERR196 - Failed to generate node for string function: '" + symbol + "'",
+                                "ERR197 - Failed to generate node for string function: '" + symbol + "'",
                                 exprtk_error_location));
 
                   return error_node();
@@ -26922,7 +27278,7 @@ namespace exprtk
                   set_error(
                      make_error(parser_error::e_syntax,
                                 current_token(),
-                                "ERR197 - Failed to generate node for overload function: '" + symbol + "'",
+                                "ERR198 - Failed to generate node for overload function: '" + symbol + "'",
                                 exprtk_error_location));
 
                   return error_node();
@@ -26948,7 +27304,7 @@ namespace exprtk
                   set_error(
                      make_error(parser_error::e_syntax,
                                 current_token(),
-                                "ERR198 - Invalid use of reserved symbol '" + symbol + "'",
+                                "ERR199 - Invalid use of reserved symbol '" + symbol + "'",
                                 exprtk_error_location));
 
                   return error_node();
@@ -27011,7 +27367,7 @@ namespace exprtk
                   set_error(
                      make_error(parser_error::e_symtab,
                                 current_token(),
-                                "ERR199 - Failed to create variable: '" + symbol + "'" +
+                                "ERR200 - Failed to create variable: '" + symbol + "'" +
                                 (error_message.empty() ? "" : " - " + error_message),
                                 exprtk_error_location));
 
@@ -27031,7 +27387,7 @@ namespace exprtk
                   set_error(
                      make_error(parser_error::e_symtab,
                                 current_token(),
-                                "ERR200 - Failed to resolve symbol: '" + symbol + "'" +
+                                "ERR201 - Failed to resolve symbol: '" + symbol + "'" +
                                 (error_message.empty() ? "" : " - " + error_message),
                                 exprtk_error_location));
                }
@@ -27043,7 +27399,7 @@ namespace exprtk
          set_error(
             make_error(parser_error::e_syntax,
                        current_token(),
-                       "ERR201 - Undefined symbol: '" + symbol + "'",
+                       "ERR202 - Undefined symbol: '" + symbol + "'",
                        exprtk_error_location));
 
          return error_node();
@@ -27157,7 +27513,7 @@ namespace exprtk
             set_error(
                make_error(parser_error::e_symtab,
                           current_token(),
-                          "ERR202 - Variable or function detected, yet symbol-table is invalid, Symbol: " + symbol,
+                          "ERR203 - Variable or function detected, yet symbol-table is invalid, Symbol: " + symbol,
                           exprtk_error_location));
 
             return error_node();
@@ -27188,7 +27544,7 @@ namespace exprtk
                   set_error(
                      make_error(parser_error::e_numeric,
                                 current_token(),
-                                "ERR203 - Failed generate node for scalar: '" + current_token().value + "'",
+                                "ERR204 - Failed generate node for scalar: '" + current_token().value + "'",
                                 exprtk_error_location));
 
                   return error_node();
@@ -27202,7 +27558,7 @@ namespace exprtk
                set_error(
                   make_error(parser_error::e_numeric,
                              current_token(),
-                             "ERR204 - Failed to convert '" + current_token().value + "' to a number",
+                             "ERR205 - Failed to convert '" + current_token().value + "' to a number",
                              exprtk_error_location));
 
                return error_node();
@@ -27229,7 +27585,7 @@ namespace exprtk
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR205 - Expected ')' instead of: '" + current_token().value + "'",
+                             "ERR206 - Expected ')' instead of: '" + current_token().value + "'",
                              exprtk_error_location));
 
                details::free_node(node_allocator_,branch);
@@ -27254,7 +27610,7 @@ namespace exprtk
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR206 - Expected ']' instead of: '" + current_token().value + "'",
+                             "ERR207 - Expected ']' instead of: '" + current_token().value + "'",
                              exprtk_error_location));
 
                details::free_node(node_allocator_,branch);
@@ -27279,7 +27635,7 @@ namespace exprtk
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR207 - Expected '}' instead of: '" + current_token().value + "'",
+                             "ERR208 - Expected '}' instead of: '" + current_token().value + "'",
                              exprtk_error_location));
 
                details::free_node(node_allocator_,branch);
@@ -27328,7 +27684,7 @@ namespace exprtk
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR208 - Premature end of expression[1]",
+                          "ERR209 - Premature end of expression[1]",
                           exprtk_error_location));
 
             return error_node();
@@ -27338,7 +27694,7 @@ namespace exprtk
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR209 - Premature end of expression[2]",
+                          "ERR210 - Premature end of expression[2]",
                           exprtk_error_location));
 
             return error_node();
@@ -29627,43 +29983,105 @@ namespace exprtk
             }
          }
 
+         const void* base_ptr(expression_node_ptr node)
+         {
+            if (node)
+            {
+               switch(node->type())
+               {
+                  case details::expression_node<T>::e_variable:
+                     return reinterpret_cast<const void*>(&static_cast<variable_node_t*>(node)->ref());
+
+                  case details::expression_node<T>::e_vecelem:
+                     return reinterpret_cast<const void*>(&static_cast<vector_elem_node_t*>(node)->ref());
+
+                  case details::expression_node<T>::e_rbvecelem:
+                     return reinterpret_cast<const void*>(&static_cast<rebasevector_elem_node_t*>(node)->ref());
+
+                  case details::expression_node<T>::e_rbveccelem:
+                     return reinterpret_cast<const void*>(&static_cast<rebasevector_celem_node_t*>(node)->ref());
+
+                  case details::expression_node<T>::e_vector:
+                     return reinterpret_cast<const void*>(static_cast<vector_node_t*>(node)->vec_holder().data());
+
+                  #ifndef exprtk_disable_string_capabilities
+                  case details::expression_node<T>::e_stringvar:
+                     return reinterpret_cast<const void*>((static_cast<stringvar_node_t*>(node)->base()));
+
+                  case details::expression_node<T>::e_stringvarrng:
+                     return reinterpret_cast<const void*>((static_cast<string_range_node_t*>(node)->base()));
+                  #endif
+                  default : return reinterpret_cast<const void*>(0);
+               }
+            }
+
+            return reinterpret_cast<const void*>(0);
+         }
+
+         bool assign_immutable_symbol(expression_node_ptr node)
+         {
+            interval_t interval;
+            const void* baseptr_addr = base_ptr(node);
+
+            exprtk_debug(("assign_immutable_symbol - base ptr addr: %p\n", baseptr_addr));
+
+            if (parser_->immutable_memory_map_.in_interval(baseptr_addr,interval))
+            {
+               typename immutable_symtok_map_t::iterator itr = parser_->immutable_symtok_map_.find(interval);
+
+               if (parser_->immutable_symtok_map_.end() != itr)
+               {
+                  token_t& token = itr->second;
+                  parser_->set_error(
+                     parser_error::make_error(parser_error::e_parser,
+                        token,
+                        "ERR211 - Symbol '" + token.value + "' cannot be assigned-to as it is immutable.",
+                        exprtk_error_location));
+               }
+               else
+                  parser_->set_synthesis_error("Unable to assign symbol is immutable.");
+
+               return true;
+            }
+
+            return false;
+         }
+
          inline expression_node_ptr synthesize_assignment_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
          {
-            if (details::is_variable_node(branch[0]))
+            if (assign_immutable_symbol(branch[0]))
+            {
+               return error_node();
+            }
+            else if (details::is_variable_node(branch[0]))
             {
                lodge_assignment(e_st_variable,branch[0]);
-
                return synthesize_expression<assignment_node_t,2>(operation,branch);
             }
             else if (details::is_vector_elem_node(branch[0]))
             {
                lodge_assignment(e_st_vecelem,branch[0]);
-
                return synthesize_expression<assignment_vec_elem_node_t, 2>(operation, branch);
             }
             else if (details::is_rebasevector_elem_node(branch[0]))
             {
                lodge_assignment(e_st_vecelem,branch[0]);
-
                return synthesize_expression<assignment_rebasevec_elem_node_t, 2>(operation, branch);
             }
             else if (details::is_rebasevector_celem_node(branch[0]))
             {
                lodge_assignment(e_st_vecelem,branch[0]);
-
                return synthesize_expression<assignment_rebasevec_celem_node_t, 2>(operation, branch);
             }
             #ifndef exprtk_disable_string_capabilities
             else if (details::is_string_node(branch[0]))
             {
                lodge_assignment(e_st_string,branch[0]);
-
                return synthesize_expression<assignment_string_node_t,2>(operation, branch);
             }
             else if (details::is_string_range_node(branch[0]))
             {
                lodge_assignment(e_st_string,branch[0]);
-
                return synthesize_expression<assignment_string_range_node_t,2>(operation, branch);
             }
             #endif
@@ -29687,6 +30105,11 @@ namespace exprtk
          inline expression_node_ptr synthesize_assignment_operation_expression(const details::operator_type& operation,
                                                                                expression_node_ptr (&branch)[2])
          {
+            if (assign_immutable_symbol(branch[0]))
+            {
+               return error_node();
+            }
+
             if (details::is_variable_node(branch[0]))
             {
                lodge_assignment(e_st_variable,branch[0]);
@@ -37006,6 +37429,9 @@ namespace exprtk
       std::string synthesis_error_;
       scope_element_manager sem_;
 
+      immutable_memory_map_t immutable_memory_map_;
+      immutable_symtok_map_t immutable_symtok_map_;
+
       lexer::helper::helper_assembly helper_assembly_;
 
       lexer::helper::commutative_inserter       commutative_inserter_;
@@ -38552,202 +38978,7 @@ namespace exprtk
       std::vector<symbol_table_t*> auxiliary_symtab_list_;
    }; // class function_compositor
 
-   template <typename T>
-   inline bool pgo_primer()
-   {
-      static const std::string expression_list[] =
-             {
-                "(y + x)",
-                "2 * (y + x)",
-                "(2 * y + 2 * x)",
-                "(y + x / y) * (x - y / x)",
-                "x / ((x + y) * (x - y)) / y",
-                "1 - ((x * y) + (y / x)) - 3",
-                "sin(2 * x) + cos(pi / y)",
-                "1 - sin(2 * x) + cos(pi / y)",
-                "sqrt(1 - sin(2 * x) + cos(pi / y) / 3)",
-                "(x^2 / sin(2 * pi / y)) -x / 2",
-                "x + (cos(y - sin(2 / x * pi)) - sin(x - cos(2 * y / pi))) - y",
-                "clamp(-1.0, sin(2 * pi * x) + cos(y / 2 * pi), +1.0)",
-                "iclamp(-1.0, sin(2 * pi * x) + cos(y / 2 * pi), +1.0)",
-                "max(3.33, min(sqrt(1 - sin(2 * x) + cos(pi / y) / 3), 1.11))",
-                "if(avg(x,y) <= x + y, x - y, x * y) + 2 * pi / x",
-                "1.1x^1 + 2.2y^2 - 3.3x^3 + 4.4y^4 - 5.5x^5 + 6.6y^6 - 7.7x^27 + 8.8y^55",
-                "(yy + xx)",
-                "2 * (yy + xx)",
-                "(2 * yy + 2 * xx)",
-                "(yy + xx / yy) * (xx - yy / xx)",
-                "xx / ((xx + yy) * (xx - yy)) / yy",
-                "1 - ((xx * yy) + (yy / xx)) - 3",
-                "sin(2 * xx) + cos(pi / yy)",
-                "1 - sin(2 * xx) + cos(pi / yy)",
-                "sqrt(1 - sin(2 * xx) + cos(pi / yy) / 3)",
-                "(xx^2 / sin(2 * pi / yy)) -xx / 2",
-                "xx + (cos(yy - sin(2 / xx * pi)) - sin(xx - cos(2 * yy / pi))) - yy",
-                "clamp(-1.0, sin(2 * pi * xx) + cos(yy / 2 * pi), +1.0)",
-                "max(3.33, min(sqrt(1 - sin(2 * xx) + cos(pi / yy) / 3), 1.11))",
-                "if(avg(xx,yy) <= xx + yy, xx - yy, xx * yy) + 2 * pi / xx",
-                "1.1xx^1 + 2.2yy^2 - 3.3xx^3 + 4.4yy^4 - 5.5xx^5 + 6.6yy^6 - 7.7xx^27 + 8.8yy^55",
-                "(1.1*(2.2*(3.3*(4.4*(5.5*(6.6*(7.7*(8.8*(9.9+x)))))))))",
-                "(((((((((x+9.9)*8.8)*7.7)*6.6)*5.5)*4.4)*3.3)*2.2)*1.1)",
-                "(x + y) * z", "x + (y * z)", "(x + y) * 7", "x + (y * 7)",
-                "(x + 7) * y", "x + (7 * y)", "(7 + x) * y", "7 + (x * y)",
-                "(2 + x) * 3", "2 + (x * 3)", "(2 + 3) * x", "2 + (3 * x)",
-                "(x + 2) * 3", "x + (2 * 3)",
-                "(x + y) * (z / w)", "(x + y) * (z / 7)", "(x + y) * (7 / z)", "(x + 7) * (y / z)",
-                "(7 + x) * (y / z)", "(2 + x) * (y / z)", "(x + 2) * (y / 3)", "(2 + x) * (y / 3)",
-                "(x + 2) * (3 / y)", "x + (y * (z / w))", "x + (y * (z / 7))", "x + (y * (7 / z))",
-                "x + (7 * (y / z))", "7 + (x * (y / z))", "2 + (x * (3 / y))", "x + (2 * (y / 4))",
-                "2 + (x * (y / 3))", "x + (2 * (3 / y))",
-                "x + ((y * z) / w)", "x + ((y * z) / 7)", "x + ((y * 7) / z)", "x + ((7 * y) / z)",
-                "7 + ((y * z) / w)", "2 + ((x * 3) / y)", "x + ((2 * y) / 3)", "2 + ((x * y) / 3)",
-                "x + ((2 * 3) / y)", "(((x + y) * z) / w)",
-                "(((x + y) * z) / 7)", "(((x + y) * 7) / z)", "(((x + 7) * y) / z)", "(((7 + x) * y) / z)",
-                "(((2 + x) * 3) / y)", "(((x + 2) * y) / 3)", "(((2 + x) * y) / 3)", "(((x + 2) * 3) / y)",
-                "((x + (y * z)) / w)", "((x + (y * z)) / 7)", "((x + (y * 7)) / y)", "((x + (7 * y)) / z)",
-                "((7 + (x * y)) / z)", "((2 + (x * 3)) / y)", "((x + (2 * y)) / 3)", "((2 + (x * y)) / 3)",
-                "((x + (2 * 3)) / y)",
-                "(xx + yy) * zz", "xx + (yy * zz)",
-                "(xx + yy) * 7", "xx + (yy * 7)",
-                "(xx + 7) * yy", "xx + (7 * yy)",
-                "(7 + xx) * yy", "7 + (xx * yy)",
-                "(2 + x) * 3", "2 + (x * 3)",
-                "(2 + 3) * x", "2 + (3 * x)",
-                "(x + 2) * 3", "x + (2 * 3)",
-                "(xx + yy) * (zz / ww)", "(xx + yy) * (zz / 7)",
-                "(xx + yy) * (7 / zz)", "(xx + 7) * (yy / zz)",
-                "(7 + xx) * (yy / zz)", "(2 + xx) * (yy / zz)",
-                "(xx + 2) * (yy / 3)", "(2 + xx) * (yy / 3)",
-                "(xx + 2) * (3 / yy)", "xx + (yy * (zz / ww))",
-                "xx + (yy * (zz / 7))", "xx + (yy * (7 / zz))",
-                "xx + (7 * (yy / zz))", "7 + (xx * (yy / zz))",
-                "2 + (xx * (3 / yy))", "xx + (2 * (yy / 4))",
-                "2 + (xx * (yy / 3))", "xx + (2 * (3 / yy))",
-                "xx + ((yy * zz) / ww)", "xx + ((yy * zz) / 7)",
-                "xx + ((yy * 7) / zz)", "xx + ((7 * yy) / zz)",
-                "7 + ((yy * zz) / ww)", "2 + ((xx * 3) / yy)",
-                "xx + ((2 * yy) / 3)", "2 + ((xx * yy) / 3)",
-                "xx + ((2 * 3) / yy)", "(((xx + yy) * zz) / ww)",
-                "(((xx + yy) * zz) / 7)", "(((xx + yy) * 7) / zz)",
-                "(((xx + 7) * yy) / zz)", "(((7 + xx) * yy) / zz)",
-                "(((2 + xx) * 3) / yy)", "(((xx + 2) * yy) / 3)",
-                "(((2 + xx) * yy) / 3)", "(((xx + 2) * 3) / yy)",
-                "((xx + (yy * zz)) / ww)", "((xx + (yy * zz)) / 7)",
-                "((xx + (yy * 7)) / yy)", "((xx + (7 * yy)) / zz)",
-                "((7 + (xx * yy)) / zz)", "((2 + (xx * 3)) / yy)",
-                "((xx + (2 * yy)) / 3)", "((2 + (xx * yy)) / 3)",
-                "((xx + (2 * 3)) / yy)"
-             };
-
-      static const std::size_t expression_list_size = sizeof(expression_list) / sizeof(std::string);
-
-      T  x = T(0);
-      T  y = T(0);
-      T  z = T(0);
-      T  w = T(0);
-      T xx = T(0);
-      T yy = T(0);
-      T zz = T(0);
-      T ww = T(0);
-
-      exprtk::symbol_table<T> symbol_table;
-      symbol_table.add_constants();
-      symbol_table.add_variable( "x", x);
-      symbol_table.add_variable( "y", y);
-      symbol_table.add_variable( "z", z);
-      symbol_table.add_variable( "w", w);
-      symbol_table.add_variable("xx",xx);
-      symbol_table.add_variable("yy",yy);
-      symbol_table.add_variable("zz",zz);
-      symbol_table.add_variable("ww",ww);
-
-      typedef typename std::deque<exprtk::expression<T> > expr_list_t;
-      expr_list_t expr_list;
-
-      const std::size_t rounds = 50;
-
-      {
-         for (std::size_t r = 0; r < rounds; ++r)
-         {
-            expr_list.clear();
-            exprtk::parser<T> parser;
-
-            for (std::size_t i = 0; i < expression_list_size; ++i)
-            {
-               exprtk::expression<T> expression;
-               expression.register_symbol_table(symbol_table);
-
-               if (!parser.compile(expression_list[i],expression))
-               {
-                  return false;
-               }
-
-               expr_list.push_back(expression);
-            }
-         }
-      }
-
-      struct execute
-      {
-         static inline T process(T& x, T& y, expression<T>& expression)
-         {
-            static const T lower_bound = T(-20);
-            static const T upper_bound = T(+20);
-            static const T delta       = T(0.1);
-
-            T total = T(0);
-
-            for (x = lower_bound; x <= upper_bound; x += delta)
-            {
-               for (y = lower_bound; y <= upper_bound; y += delta)
-               {
-                  total += expression.value();
-               }
-            }
-
-            return total;
-         }
-      };
-
-      for (std::size_t i = 0; i < expr_list.size(); ++i)
-      {
-         execute::process( x,  y, expr_list[i]);
-         execute::process(xx, yy, expr_list[i]);
-      }
-
-      {
-         for (std::size_t i = 0; i < 10000; ++i)
-         {
-            const T v = T(123.456 + i);
-
-            if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T, 1>::result(v),details::numeric::pow(v,T(1)))))
-               return false;
-
-            #define else_stmt(N)                                                                                                           \
-            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,N>::result(v),details::numeric::pow(v,T(N))))) \
-               return false;                                                                                                               \
-
-            else_stmt( 2) else_stmt( 3) else_stmt( 4) else_stmt( 5)
-            else_stmt( 6) else_stmt( 7) else_stmt( 8) else_stmt( 9)
-            else_stmt(10) else_stmt(11) else_stmt(12) else_stmt(13)
-            else_stmt(14) else_stmt(15) else_stmt(16) else_stmt(17)
-            else_stmt(18) else_stmt(19) else_stmt(20) else_stmt(21)
-            else_stmt(22) else_stmt(23) else_stmt(24) else_stmt(25)
-            else_stmt(26) else_stmt(27) else_stmt(28) else_stmt(29)
-            else_stmt(30) else_stmt(31) else_stmt(32) else_stmt(33)
-            else_stmt(34) else_stmt(35) else_stmt(36) else_stmt(37)
-            else_stmt(38) else_stmt(39) else_stmt(40) else_stmt(41)
-            else_stmt(42) else_stmt(43) else_stmt(44) else_stmt(45)
-            else_stmt(46) else_stmt(47) else_stmt(48) else_stmt(49)
-            else_stmt(50) else_stmt(51) else_stmt(52) else_stmt(53)
-            else_stmt(54) else_stmt(55) else_stmt(56) else_stmt(57)
-            else_stmt(58) else_stmt(59) else_stmt(60) else_stmt(61)
-         }
-      }
-
-      return true;
-   }
-}
+} // namespace exprtk
 
 #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
 #   ifndef NOMINMAX
@@ -39023,6 +39254,9 @@ namespace exprtk
 {
    namespace rtl { namespace io { namespace file { namespace details
    {
+      using ::exprtk::details::char_ptr;
+      using ::exprtk::details::char_cptr;
+
       enum file_mode
       {
          e_error = 0,
@@ -39131,11 +39365,11 @@ namespace exprtk
             switch (mode)
             {
                case e_write : reinterpret_cast<std::ofstream*>(stream_ptr)->
-                                 write(reinterpret_cast<const char*>(view.begin() + offset), amount * sizeof(typename View::value_t));
+                                 write(reinterpret_cast<char_cptr>(view.begin() + offset), amount * sizeof(typename View::value_t));
                               break;
 
                case e_rdwrt : reinterpret_cast<std::fstream*>(stream_ptr)->
-                                 write(reinterpret_cast<const char*>(view.begin() + offset) , amount * sizeof(typename View::value_t));
+                                 write(reinterpret_cast<char_cptr>(view.begin() + offset) , amount * sizeof(typename View::value_t));
                               break;
 
                default      : return false;
@@ -39150,11 +39384,11 @@ namespace exprtk
             switch (mode)
             {
                case e_read  : reinterpret_cast<std::ifstream*>(stream_ptr)->
-                                 read(reinterpret_cast<char*>(view.begin() + offset), amount * sizeof(typename View::value_t));
+                                 read(reinterpret_cast<char_ptr>(view.begin() + offset), amount * sizeof(typename View::value_t));
                               break;
 
                case e_rdwrt : reinterpret_cast<std::fstream*>(stream_ptr)->
-                                 read(reinterpret_cast<char*>(view.begin() + offset) , amount * sizeof(typename View::value_t));
+                                 read(reinterpret_cast<char_ptr>(view.begin() + offset) , amount * sizeof(typename View::value_t));
                               break;
 
                default      : return false;
@@ -39218,12 +39452,11 @@ namespace exprtk
       template <typename T>
       file_descriptor* make_handle(T v)
       {
+         const std::size_t fd_size    = sizeof(details::file_descriptor*);
          details::file_descriptor* fd = reinterpret_cast<file_descriptor*>(0);
 
-         const std::size_t fd_size = sizeof(details::file_descriptor*);
-
-         std::memcpy(reinterpret_cast<char*>(&fd),
-                     reinterpret_cast<const char*>(&v),
+         std::memcpy(reinterpret_cast<char_ptr >(&fd),
+                     reinterpret_cast<char_cptr>(&v ),
                      fd_size);
          return fd;
       }
@@ -39264,18 +39497,18 @@ namespace exprtk
 
       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
       {
-         std::string file_name = to_str(string_t(parameters[0]));
-         std::string access;
+         const std::string file_name = to_str(string_t(parameters[0]));
 
          if (file_name.empty())
             return T(0);
 
-         if (0 == ps_index)
-            access = "r";
-         else if (0 == string_t(parameters[1]).size())
+         if ((1 == ps_index) && (0 == string_t(parameters[1]).size()))
+         {
             return T(0);
-         else
-            access = to_str(string_t(parameters[1]));
+         }
+
+         const std::string access =
+            (0 == ps_index) ? "r" : to_str(string_t(parameters[1]));
 
          details::file_descriptor* fd = new details::file_descriptor(file_name,access);
 
@@ -40696,18 +40929,22 @@ namespace exprtk
 {
    namespace information
    {
-      static const char* library = "Mathematical Expression Toolkit";
-      static const char* version = "2.7182818284590452353602874713526"
-                                   "624977572470936999595749669676277"
-                                   "240766303535475945713821785251664"
-                                   "274274663919320030599218174135966";
-      static const char* date    = "20220101";
+      using ::exprtk::details::char_cptr;
+
+      static char_cptr library = "Mathematical Expression Toolkit";
+      static char_cptr version = "2.71828182845904523536028747135266"
+                                 "2497757247093699959574966967627724"
+                                 "0766303535475945713821785251664274"
+                                 "2746639193200305992181741359662904";
+      static char_cptr date    = "20230101";
+      static char_cptr min_cpp = "199711L";
 
       static inline std::string data()
       {
          static const std::string info_str = std::string(library) +
                                              std::string(" v") + std::string(version) +
-                                             std::string(" (") + date + std::string(")");
+                                             std::string(" (") + date + std::string(")") +
+                                             std::string(" (") + min_cpp + std::string(")");
          return info_str;
       }
 
diff --git a/server/src/main.cpp b/server/src/main.cpp
index eb4feaa..d24d605 100644
--- a/server/src/main.cpp
+++ b/server/src/main.cpp
@@ -270,8 +270,19 @@ void CMain::WatchdogMessage(int ClientNetID, double load_1, double load_5, doubl
         typedef exprtk::expression<double>   expression_t;
         typedef exprtk::parser<double>       parser_t;
         const std::string expression_string = Watchdog(ID)->m_aRule;
+        int ClientID = ClientNetToClient(ClientNetID);
+        std::string username = Client(ClientID)->m_aUsername;
+        std::string name = Client(ClientID)->m_aName;
+        std::string type = Client(ClientID)->m_aType;
+        std::string host = Client(ClientID)->m_aHost;
+        std::string location = Client(ClientID)->m_aLocation;
 
         symbol_table_t symbol_table;
+        symbol_table.add_stringvar("username", username);
+        symbol_table.add_stringvar("name", name);
+        symbol_table.add_stringvar("type", type);
+        symbol_table.add_stringvar("host", host);
+        symbol_table.add_stringvar("location", location);
         symbol_table.add_variable("load_1",load_1);
         symbol_table.add_variable("load_5",load_5);
         symbol_table.add_variable("load_15",load_15);
@@ -310,7 +321,6 @@ void CMain::WatchdogMessage(int ClientNetID, double load_1, double load_5, doubl
 
         if (expression.value() > 0)
         {
-	    int ClientID = ClientNetToClient(ClientNetID);
             time_t currentStamp = (long long)time(/*ago*/0);
             if ((currentStamp-Client(ClientID)->m_AlarmLastTime) > Watchdog(ID)->m_aInterval)
             {
@@ -330,11 +340,11 @@ void CMain::WatchdogMessage(int ClientNetID, double load_1, double load_5, doubl
                     sprintf(encodeBuffer, "【告警名称】 %s \n\n【告警时间】 %s  \n\n【用户名】 %s \n\n【节点名】 %s \n\n【虚拟化】 %s \n\n【主机名】 %s \n\n【位  置】 %s",
                             Watchdog(ID)->m_aName,
                             standardTime,
-                            Client(ClientID)->m_aUsername,
-                            Client(ClientID)->m_aName,
-                            Client(ClientID)->m_aType,
-                            Client(ClientID)->m_aHost,
-                            Client(ClientID)->m_aLocation);
+                            username.c_str(),
+                            name.c_str(),
+                            type.c_str(),
+                            host.c_str(),
+                            location.c_str());
                     char *encodeUrl = curl_easy_escape(curl, encodeBuffer, strlen(encodeBuffer));
 
                     //standard url