Patch 9.0.1060
problem:    Private and public object members are not implemented yet.
Solution:   Implement private and public object members.
Files:      src/vim9class.c, src/errors.h, src/structs.h, src/vim9expr.c,
            src/eval.c, src/testdir/test_vim9_class.vim


*** ../vim-9.0.1059/src/vim9class.c     2022-12-14 15:06:07.061956386 +0000
--- src/vim9class.c     2022-12-14 19:37:37.410578885 +0000
***************
*** 110,128 ****
            break;
        }
  
-       // "this.varname"
        // "this._varname"
!       // TODO:
!       //      "public this.varname"
!       if (STRNCMP(line, "this", 4) == 0)
        {
!           if (line[4] != '.' || !eval_isnamec1(line[5]))
            {
!               semsg(_(e_invalid_object_member_declaration_str), line);
                break;
            }
!           char_u *varname = line + 5;
            char_u *varname_end = to_name_end(varname, FALSE);
  
            char_u *colon = skipwhite(varname_end);
            char_u *type_arg = colon;
--- 110,149 ----
            break;
        }
  
        // "this._varname"
!       // "this.varname"
!       // "public this.varname"
!       int has_public = FALSE;
!       if (checkforcmd(&p, "public", 3))
        {
!           if (STRNCMP(line, "public", 6) != 0)
!           {
!               semsg(_(e_command_cannot_be_shortened_str), line);
!               break;
!           }
!           has_public = TRUE;
!           p = skipwhite(line + 6);
! 
!           if (STRNCMP(p, "this", 4) != 0)
            {
!               emsg(_(e_public_must_be_followed_by_this));
                break;
            }
!       }
!       if (STRNCMP(p, "this", 4) == 0)
!       {
!           if (p[4] != '.' || !eval_isnamec1(p[5]))
!           {
!               semsg(_(e_invalid_object_member_declaration_str), p);
!               break;
!           }
!           char_u *varname = p + 5;
            char_u *varname_end = to_name_end(varname, FALSE);
+           if (*varname == '_' && has_public)
+           {
+               
semsg(_(e_public_object_member_name_cannot_start_with_underscore_str), line);
+               break;
+           }
  
            char_u *colon = skipwhite(varname_end);
            char_u *type_arg = colon;
***************
*** 199,204 ****
--- 220,228 ----
            objmember_T *m = ((objmember_T *)objmembers.ga_data)
                                                          + objmembers.ga_len;
            m->om_name = vim_strnsave(varname, varname_end - varname);
+           m->om_access = has_public ? ACCESS_ALL
+                           : *varname == '_' ? ACCESS_PRIVATE
+                           : ACCESS_READ;
            m->om_type = type;
            if (expr_end > expr_start)
                m->om_init = vim_strnsave(expr_start, expr_end - expr_start);
***************
*** 551,556 ****
--- 575,587 ----
            objmember_T *m = &cl->class_obj_members[i];
            if (STRNCMP(name, m->om_name, len) == 0 && m->om_name[len] == NUL)
            {
+               if (*name == '_')
+               {
+                   semsg(_(e_cannot_access_private_object_member_str),
+                                                                  m->om_name);
+                   return FAIL;
+               }
+ 
                // The object only contains a pointer to the class, the member
                // values array follows right after that.
                object_T *obj = rettv->vval.v_object;
*** ../vim-9.0.1059/src/errors.h        2022-12-13 21:14:19.219930894 +0000
--- src/errors.h        2022-12-14 20:45:06.332433051 +0000
***************
*** 3378,3381 ****
--- 3378,3391 ----
        INIT(= N_("E1329: Cannot get object member type from initializer: %s"));
  EXTERN char e_invalid_type_for_object_member_str[]
        INIT(= N_("E1330: Invalid type for object member: %s"));
+ EXTERN char e_public_must_be_followed_by_this[]
+       INIT(= N_("E1331: Public must be followed by \"this\""));
+ EXTERN char e_public_object_member_name_cannot_start_with_underscore_str[]
+       INIT(= N_("E1332: Public object member name cannot start with 
underscore: %s"));
+ EXTERN char e_cannot_access_private_object_member_str[]
+       INIT(= N_("E1333: Cannot access private object member: %s"));
+ EXTERN char e_object_member_not_found_str[]
+       INIT(= N_("E1334: Object member not found: %s"));
+ EXTERN char e_object_member_is_not_writable_str[]
+       INIT(= N_("E1335: Object member is not writable: %s"));
  #endif
*** ../vim-9.0.1059/src/structs.h       2022-12-10 18:42:09.094378801 +0000
--- src/structs.h       2022-12-14 19:07:47.903514703 +0000
***************
*** 1459,1469 ****
--- 1459,1476 ----
      type_T    *type_decl;         // declared type or equal to type_current
  } type2_T;
  
+ typedef enum {
+     ACCESS_PRIVATE,   // read/write only inside th class
+     ACCESS_READ,      // read everywhere, write only inside th class
+     ACCESS_ALL                // read/write everywhere
+ } omacc_T;
+ 
  /*
   * Entry for an object member variable.
   */
  typedef struct {
      char_u    *om_name;   // allocated
+     omacc_T   om_access;
      type_T    *om_type;
      char_u    *om_init;   // allocated
  } objmember_T;
***************
*** 1720,1726 ****
      def_status_T uf_def_status; // UF_NOT_COMPILED, UF_TO_BE_COMPILED, etc.
      int               uf_dfunc_idx;   // only valid if uf_def_status is 
UF_COMPILED
  
!     class_T   *uf_class;      // for object method and constructor
  
      garray_T  uf_args;        // arguments, including optional arguments
      garray_T  uf_def_args;    // default argument expressions
--- 1727,1734 ----
      def_status_T uf_def_status; // UF_NOT_COMPILED, UF_TO_BE_COMPILED, etc.
      int               uf_dfunc_idx;   // only valid if uf_def_status is 
UF_COMPILED
  
!     class_T   *uf_class;      // for object method and constructor; does not
!                               // count for class_refcount
  
      garray_T  uf_args;        // arguments, including optional arguments
      garray_T  uf_def_args;    // default argument expressions
*** ../vim-9.0.1059/src/vim9expr.c      2022-12-10 18:42:09.094378801 +0000
--- src/vim9expr.c      2022-12-14 19:44:13.638410537 +0000
***************
*** 281,286 ****
--- 281,293 ----
            objmember_T *m = &cl->class_obj_members[i];
            if (STRNCMP(name, m->om_name, len) == 0 && m->om_name[len] == NUL)
            {
+               if (*name == '_' && cctx->ctx_ufunc->uf_class != cl)
+               {
+                   semsg(_(e_cannot_access_private_object_member_str),
+                                                                  m->om_name);
+                   return FAIL;
+               }
+ 
                generate_GET_OBJ_MEMBER(cctx, i, m->om_type);
  
                *arg = name_end;
*** ../vim-9.0.1059/src/eval.c  2022-12-14 17:49:56.611042669 +0000
--- src/eval.c  2022-12-14 20:43:38.608552363 +0000
***************
*** 1194,1199 ****
--- 1194,1200 ----
      while (*p == '[' || (*p == '.' && p[1] != '=' && p[1] != '.'))
      {
        if (*p == '.' && lp->ll_tv->v_type != VAR_DICT
+                     && lp->ll_tv->v_type != VAR_OBJECT
                      && lp->ll_tv->v_type != VAR_CLASS)
        {
            if (!quiet)
***************
*** 1203,1208 ****
--- 1204,1210 ----
        if (lp->ll_tv->v_type != VAR_LIST
                && lp->ll_tv->v_type != VAR_DICT
                && lp->ll_tv->v_type != VAR_BLOB
+               && lp->ll_tv->v_type != VAR_OBJECT
                && lp->ll_tv->v_type != VAR_CLASS)
        {
            if (!quiet)
***************
*** 1509,1518 ****
  
            lp->ll_tv = &lp->ll_li->li_tv;
        }
!       else  // v_type == VAR_CLASS
        {
!           // TODO: check object members and methods if
!           // "key" points name start, "p" to the end
        }
      }
  
--- 1511,1565 ----
  
            lp->ll_tv = &lp->ll_li->li_tv;
        }
!       else  // v_type == VAR_CLASS || v_type == VAR_OBJECT
        {
!           class_T *cl = (lp->ll_tv->v_type == VAR_OBJECT
!                                          && lp->ll_tv->vval.v_object != NULL)
!                           ? lp->ll_tv->vval.v_object->obj_class
!                           : lp->ll_tv->vval.v_class;
!           // TODO: what if class is NULL?
!           if (cl != NULL)
!           {
!               lp->ll_valtype = NULL;
!               for (int i = 0; i < cl->class_obj_member_count; ++i)
!               {
!                   objmember_T *om = cl->class_obj_members + i;
!                   if (STRNCMP(om->om_name, key, p - key) == 0
!                                               && om->om_name[p - key] == NUL)
!                   {
!                       switch (om->om_access)
!                       {
!                           case ACCESS_PRIVATE:
!                                   
semsg(_(e_cannot_access_private_object_member_str),
!                                           om->om_name);
!                                   return NULL;
!                           case ACCESS_READ:
!                                   if (!(flags & GLV_READ_ONLY))
!                                   {
!                                       
semsg(_(e_object_member_is_not_writable_str),
!                                               om->om_name);
!                                       return NULL;
!                                   }
!                                   break;
!                           case ACCESS_ALL:
!                                   break;
!                       }
! 
!                       lp->ll_valtype = om->om_type;
! 
!                       if (lp->ll_tv->v_type == VAR_OBJECT)
!                           lp->ll_tv = ((typval_T *)(
!                                           lp->ll_tv->vval.v_object + 1)) + i;
!                       // TODO: what about a class?
!                       break;
!                   }
!               }
!               if (lp->ll_valtype == NULL)
!               {
!                   semsg(_(e_object_member_not_found_str), key);
!                   return NULL;
!               }
!           }
        }
      }
  
***************
*** 1640,1646 ****
      else
      {
        /*
!        * Assign to a List or Dictionary item.
         */
        if ((flags & (ASSIGN_CONST | ASSIGN_FINAL))
                                             && (flags & ASSIGN_FOR_LOOP) == 0)
--- 1687,1693 ----
      else
      {
        /*
!        * Assign to a List, Dictionary or Object item.
         */
        if ((flags & (ASSIGN_CONST | ASSIGN_FINAL))
                                             && (flags & ASSIGN_FOR_LOOP) == 0)
*** ../vim-9.0.1059/src/testdir/test_vim9_class.vim     2022-12-14 
17:30:34.105232856 +0000
--- src/testdir/test_vim9_class.vim     2022-12-14 20:52:05.499900404 +0000
***************
*** 283,288 ****
--- 283,315 ----
    v9.CheckScriptFailure(lines, 'E1330:')
  enddef
  
+ def Test_class_object_member_access()
+   var lines =<< trim END
+       vim9script
+       class Triple
+          this._one = 1
+          this.two = 2
+          public this.three = 3
+ 
+          def GetOne(): number
+            return this._one
+          enddef
+       endclass
+ 
+       var trip = Triple.new()
+       assert_equal(1, trip.GetOne())
+       assert_equal(2, trip.two)
+       assert_equal(3, trip.three)
+       assert_fails('echo trip._one', 'E1333')
+ 
+       assert_fails('trip._one = 11', 'E1333')
+       assert_fails('trip.two = 22', 'E1335')
+       trip.three = 33
+       assert_equal(33, trip.three)
+   END
+   v9.CheckScriptSuccess(lines)
+ enddef
+ 
  def Test_class_object_to_string()
    var lines =<< trim END
        vim9script
*** ../vim-9.0.1059/src/version.c       2022-12-14 17:49:56.611042669 +0000
--- src/version.c       2022-12-14 20:51:05.867973365 +0000
***************
*** 697,698 ****
--- 697,700 ----
  {   /* Add new patch number below this line */
+ /**/
+     1060,
  /**/

-- 
       "To whoever finds this note -
       I have been imprisoned by my father who wishes me to marry
       against my will.  Please please please please come and rescue me.
       I am in the tall tower of Swamp Castle."
   SIR LAUNCELOT's eyes light up with holy inspiration.
                 "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///                                                                      \\\
\\\        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/20221214210008.EA8ED1C0CF1%40moolenaar.net.

Raspunde prin e-mail lui