patch 9.0.1001: classes are not documented or implemented yet

Problem:    Classes are not documented or implemented yet.
Solution:   Make the first steps at documenting Vim9 objects, classes and
            interfaces.  Make initial choices for the syntax.  Add a skeleton
            implementation.  Add "public" and "this" in the command table.
diff --git a/src/Make_ami.mak b/src/Make_ami.mak
index a642d91..9e9ebe3 100644
--- a/src/Make_ami.mak
+++ b/src/Make_ami.mak
@@ -174,6 +174,7 @@
 	userfunc.c \
 	version.c \
 	viminfo.c \
+	vim9class.c \
 	vim9cmds.c \
 	vim9compile.c \
 	vim9execute.c \
diff --git a/src/Make_cyg_ming.mak b/src/Make_cyg_ming.mak
index b559467..4261256 100644
--- a/src/Make_cyg_ming.mak
+++ b/src/Make_cyg_ming.mak
@@ -851,6 +851,7 @@
 	$(OUTDIR)/usercmd.o \
 	$(OUTDIR)/userfunc.o \
 	$(OUTDIR)/version.o \
+	$(OUTDIR)/vim9class.o \
 	$(OUTDIR)/vim9cmds.o \
 	$(OUTDIR)/vim9compile.o \
 	$(OUTDIR)/vim9execute.o \
@@ -1251,6 +1252,8 @@
 
 $(OUTDIR)/version.o: version.c $(INCL) version.h
 
+$(OUTDIR)/vim9class.o: vim9class.c $(INCL) vim9.h
+
 $(OUTDIR)/vim9cmds.o: vim9cmds.c $(INCL) vim9.h
 
 $(OUTDIR)/vim9compile.o: vim9compile.c $(INCL) vim9.h
diff --git a/src/Make_mvc.mak b/src/Make_mvc.mak
index 501446e..b478d9a 100644
--- a/src/Make_mvc.mak
+++ b/src/Make_mvc.mak
@@ -735,6 +735,7 @@
 	$(OUTDIR)\undo.obj \
 	$(OUTDIR)\usercmd.obj \
 	$(OUTDIR)\userfunc.obj \
+	$(OUTDIR)\vim9class.obj \
 	$(OUTDIR)\vim9cmds.obj \
 	$(OUTDIR)\vim9compile.obj \
 	$(OUTDIR)\vim9execute.obj \
@@ -1708,6 +1709,8 @@
 
 $(OUTDIR)/version.obj:	$(OUTDIR) version.c  $(INCL) version.h
 
+$(OUTDIR)/vim9class.obj:	$(OUTDIR) vim9class.c  $(INCL) vim9.h
+
 $(OUTDIR)/vim9cmds.obj:	$(OUTDIR) vim9cmds.c  $(INCL) vim9.h
 
 $(OUTDIR)/vim9compile.obj:	$(OUTDIR) vim9compile.c  $(INCL) vim9.h
@@ -1915,6 +1918,7 @@
 	proto/undo.pro \
 	proto/usercmd.pro \
 	proto/userfunc.pro \
+	proto/vim9class.pro \
 	proto/vim9cmds.pro \
 	proto/vim9compile.pro \
 	proto/vim9execute.pro \
diff --git a/src/Make_vms.mms b/src/Make_vms.mms
index 53e1ce1..8dd5454 100644
--- a/src/Make_vms.mms
+++ b/src/Make_vms.mms
@@ -409,6 +409,7 @@
 	usercmd.c \
 	userfunc.c \
 	version.c \
+	vim9class.c \
 	vim9cmds.c \
 	vim9compile.c \
 	vim9execute.c \
@@ -534,6 +535,7 @@
 	usercmd.obj \
 	userfunc.obj \
 	version.obj \
+	vim9class.obj \
 	vim9cmds.obj \
 	vim9compile.obj \
 	vim9execute.obj \
@@ -1122,6 +1124,10 @@
  ascii.h keymap.h termdefs.h macros.h structs.h regexp.h \
  gui.h beval.h [.proto]gui_beval.pro option.h ex_cmds.h proto.h \
  errors.h globals.h version.h
+vim9class.obj : vim9class.c vim.h [.auto]config.h feature.h os_unix.h \
+ ascii.h keymap.h termdefs.h macros.h structs.h regexp.h \
+ gui.h beval.h [.proto]gui_beval.pro option.h ex_cmds.h proto.h \
+ errors.h globals.h version.h
 vim9cmds.obj : vim9cmds.c vim.h [.auto]config.h feature.h os_unix.h \
  ascii.h keymap.h termdefs.h macros.h structs.h regexp.h \
  gui.h beval.h [.proto]gui_beval.pro option.h ex_cmds.h proto.h \
diff --git a/src/Makefile b/src/Makefile
index 7f9d173..43249c2 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -1584,6 +1584,7 @@
 	usercmd.c \
 	userfunc.c \
 	version.c \
+	vim9class.c \
 	vim9cmds.c \
 	vim9compile.c \
 	vim9execute.c \
@@ -1741,6 +1742,7 @@
 	objects/usercmd.o \
 	objects/userfunc.o \
 	objects/version.o \
+	objects/vim9class.o \
 	objects/vim9cmds.o \
 	objects/vim9compile.o \
 	objects/vim9execute.o \
@@ -1931,6 +1933,7 @@
 	usercmd.pro \
 	userfunc.pro \
 	version.pro \
+	vim9class.pro \
 	vim9cmds.pro \
 	vim9compile.pro \
 	vim9execute.pro \
@@ -3489,6 +3492,9 @@
 objects/userfunc.o: userfunc.c
 	$(CCC) -o $@ userfunc.c
 
+objects/vim9class.o: vim9class.c
+	$(CCC) -o $@ vim9class.c
+
 objects/vim9cmds.o: vim9cmds.c
 	$(CCC) -o $@ vim9cmds.c
 
@@ -4168,6 +4174,11 @@
  proto/gui_beval.pro structs.h regexp.h gui.h libvterm/include/vterm.h \
  libvterm/include/vterm_keycodes.h alloc.h ex_cmds.h spell.h proto.h \
  globals.h errors.h version.h
+objects/vim9class.o: vim9class.c vim.h protodef.h auto/config.h feature.h os_unix.h \
+ auto/osdef.h ascii.h keymap.h termdefs.h macros.h option.h beval.h \
+ proto/gui_beval.pro structs.h regexp.h gui.h libvterm/include/vterm.h \
+ libvterm/include/vterm_keycodes.h alloc.h ex_cmds.h spell.h proto.h \
+ globals.h errors.h vim9.h
 objects/vim9cmds.o: vim9cmds.c vim.h protodef.h auto/config.h feature.h os_unix.h \
  auto/osdef.h ascii.h keymap.h termdefs.h macros.h option.h beval.h \
  proto/gui_beval.pro structs.h regexp.h gui.h libvterm/include/vterm.h \
diff --git a/src/errors.h b/src/errors.h
index 2fc80c5..cf30221 100644
--- a/src/errors.h
+++ b/src/errors.h
@@ -3345,3 +3345,7 @@
 	INIT(= N_("E1312: Not allowed to change the window layout in this autocmd"));
 EXTERN char e_not_allowed_to_add_or_remove_entries_str[]
 	INIT(= N_("E1313: Not allowed to add or remove entries (%s)"));
+#ifdef FEAT_EVAL
+EXTERN char e_class_name_must_start_with_uppercase_letter_str[]
+	INIT(= N_("E1314: Class name must start with an uppercase letter: %s"));
+#endif
diff --git a/src/ex_cmdidxs.h b/src/ex_cmdidxs.h
index fd4b155..658f05e 100644
--- a/src/ex_cmdidxs.h
+++ b/src/ex_cmdidxs.h
@@ -21,16 +21,16 @@
   /* n */ 308,
   /* o */ 328,
   /* p */ 340,
-  /* q */ 379,
-  /* r */ 382,
-  /* s */ 402,
-  /* t */ 472,
-  /* u */ 518,
-  /* v */ 529,
-  /* w */ 550,
-  /* x */ 564,
-  /* y */ 574,
-  /* z */ 575
+  /* q */ 380,
+  /* r */ 383,
+  /* s */ 403,
+  /* t */ 473,
+  /* u */ 520,
+  /* v */ 531,
+  /* w */ 552,
+  /* x */ 566,
+  /* y */ 576,
+  /* z */ 577
 };
 
 /*
@@ -56,11 +56,11 @@
   /* m */ {  1,  0,  0,  0,  7,  0,  0,  0,  0,  0, 10,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 16 },
   /* n */ {  0,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  5,  8, 10,  0,  0,  0,  0,  0, 17,  0,  0,  0,  0,  0 },
   /* o */ {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  2,  5,  0,  0,  0,  0,  0,  0,  9,  0, 11,  0,  0,  0 },
-  /* p */ {  1,  0,  3,  0,  4,  0,  0,  0,  0,  0,  0,  0,  0,  0,  7,  9,  0,  0, 16, 17, 26,  0, 27,  0, 28,  0 },
+  /* p */ {  1,  0,  3,  0,  4,  0,  0,  0,  0,  0,  0,  0,  0,  0,  7,  9,  0,  0, 16, 17, 26,  0, 28,  0, 29,  0 },
   /* q */ {  2,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0 },
   /* r */ {  0,  0,  0,  0,  0,  0,  0,  0, 12,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 14, 19,  0,  0,  0,  0 },
   /* s */ {  2,  6, 15,  0, 19, 23,  0, 25, 26,  0,  0, 29, 31, 35, 39, 41,  0, 50,  0, 51,  0, 64, 65,  0, 66,  0 },
-  /* t */ {  2,  0, 19,  0, 24, 26,  0, 27,  0, 28,  0, 29, 33, 36, 38, 39,  0, 40, 42,  0, 43,  0,  0,  0, 45,  0 },
+  /* t */ {  2,  0, 19,  0, 24, 26,  0, 27,  0, 29,  0, 30, 34, 37, 39, 40,  0, 41, 43,  0, 44,  0,  0,  0, 46,  0 },
   /* u */ {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 10,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0 },
   /* v */ {  1,  0,  0,  0,  2,  0,  0,  0,  5,  0,  0,  0, 12, 15,  0,  0,  0,  0, 18,  0, 19,  0,  0,  0,  0,  0 },
   /* w */ {  2,  0,  0,  0,  0,  0,  0,  3,  4,  0,  0,  0,  0,  8,  0,  9, 10,  0,  0,  0, 12, 13,  0,  0,  0,  0 },
@@ -69,4 +69,4 @@
   /* z */ {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0 }
 };
 
-static const int command_count = 592;
+static const int command_count = 594;
diff --git a/src/ex_cmds.h b/src/ex_cmds.h
index ed954ef..c6f85ce 100644
--- a/src/ex_cmds.h
+++ b/src/ex_cmds.h
@@ -126,7 +126,7 @@
 EXCMD(CMD_aboveleft,	"aboveleft",	ex_wrongmodifier,
 	EX_NEEDARG|EX_EXTRA|EX_NOTRLCOM,
 	ADDR_NONE),
-EXCMD(CMD_abstract,	"abstract",	ex_ni,
+EXCMD(CMD_abstract,	"abstract",	ex_class,
 	EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
 	ADDR_NONE),
 EXCMD(CMD_all,		"all",		ex_all,
@@ -354,7 +354,7 @@
 EXCMD(CMD_clast,	"clast",	ex_cc,
 	EX_RANGE|EX_COUNT|EX_TRLBAR|EX_BANG,
 	ADDR_UNSIGNED),
-EXCMD(CMD_class,	"class",	ex_ni,
+EXCMD(CMD_class,	"class",	ex_class,
 	EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK|EX_EXPORT,
 	ADDR_NONE),
 EXCMD(CMD_close,	"close",	ex_close,
@@ -567,16 +567,16 @@
 EXCMD(CMD_endif,	"endif",	ex_endif,
 	EX_TRLBAR|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK|EX_WHOLE,
 	ADDR_NONE),
-EXCMD(CMD_endinterface,	"endinterface",	ex_ni,
+EXCMD(CMD_endinterface,	"endinterface",	ex_wrongmodifier,
 	EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
 	ADDR_NONE),
-EXCMD(CMD_endclass,	"endclass",	ex_ni,
+EXCMD(CMD_endclass,	"endclass",	ex_wrongmodifier,
 	EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
 	ADDR_NONE),
 EXCMD(CMD_enddef,	"enddef",	ex_endfunction,
 	EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK|EX_WHOLE,
 	ADDR_NONE),
-EXCMD(CMD_endenum,	"endenum",	ex_ni,
+EXCMD(CMD_endenum,	"endenum",	ex_wrongmodifier,
 	EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
 	ADDR_NONE),
 EXCMD(CMD_endfunction,	"endfunction",	ex_endfunction,
@@ -594,7 +594,7 @@
 EXCMD(CMD_enew,		"enew",		ex_edit,
 	EX_BANG|EX_TRLBAR,
 	ADDR_NONE),
-EXCMD(CMD_enum,		"enum",		ex_ni,
+EXCMD(CMD_enum,		"enum",		ex_enum,
 	EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK|EX_EXPORT,
 	ADDR_NONE),
 EXCMD(CMD_eval,		"eval",		ex_eval,
@@ -756,7 +756,7 @@
 EXCMD(CMD_intro,	"intro",	ex_intro,
 	EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
 	ADDR_NONE),
-EXCMD(CMD_interface,	"interface",	ex_ni,
+EXCMD(CMD_interface,	"interface",	ex_interface,
 	EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
 	ADDR_NONE),
 EXCMD(CMD_isearch,	"isearch",	ex_findpat,
@@ -1215,6 +1215,9 @@
 EXCMD(CMD_put,		"put",		ex_put,
 	EX_RANGE|EX_WHOLEFOLD|EX_BANG|EX_REGSTR|EX_TRLBAR|EX_ZEROR|EX_CMDWIN|EX_LOCK_OK|EX_MODIFY,
 	ADDR_LINES),
+EXCMD(CMD_public,	"public",	ex_wrongmodifier,
+	EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
+	ADDR_NONE),
 EXCMD(CMD_pwd,		"pwd",		ex_pwd,
 	EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
 	ADDR_NONE),
@@ -1488,7 +1491,7 @@
 EXCMD(CMD_startreplace,	"startreplace",	ex_startinsert,
 	EX_BANG|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
 	ADDR_NONE),
-EXCMD(CMD_static,	"static",	ex_ni,
+EXCMD(CMD_static,	"static",	ex_wrongmodifier,
 	EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
 	ADDR_NONE),
 EXCMD(CMD_stopinsert,	"stopinsert",	ex_stopinsert,
@@ -1614,6 +1617,9 @@
 EXCMD(CMD_throw,	"throw",	ex_throw,
 	EX_EXTRA|EX_NEEDARG|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK|EX_WHOLE,
 	ADDR_NONE),
+EXCMD(CMD_this,		"this",		ex_wrongmodifier,
+	EX_EXTRA|EX_NEEDARG|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK|EX_WHOLE,
+	ADDR_NONE),
 EXCMD(CMD_tjump,	"tjump",	ex_tag,
 	EX_BANG|EX_TRLBAR|EX_WORD1,
 	ADDR_NONE),
@@ -1665,7 +1671,7 @@
 EXCMD(CMD_tunmap,	"tunmap",	ex_unmap,
 	EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK,
 	ADDR_NONE),
-EXCMD(CMD_type,		"type",		ex_ni,
+EXCMD(CMD_type,		"type",		ex_type,
 	EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK|EX_EXPORT,
 	ADDR_NONE),
 EXCMD(CMD_undo,		"undo",		ex_undo,
diff --git a/src/ex_docmd.c b/src/ex_docmd.c
index 218b7ed..660d32e 100644
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -267,6 +267,7 @@
 # define ex_breaklist		ex_ni
 # define ex_call		ex_ni
 # define ex_catch		ex_ni
+# define ex_class		ex_ni
 # define ex_compiler		ex_ni
 # define ex_continue		ex_ni
 # define ex_debug		ex_ni
@@ -282,10 +283,12 @@
 # define ex_endif		ex_ni
 # define ex_endtry		ex_ni
 # define ex_endwhile		ex_ni
+# define ex_enum		ex_ni
 # define ex_eval		ex_ni
 # define ex_execute		ex_ni
-# define ex_incdec		ex_ni
 # define ex_finally		ex_ni
+# define ex_incdec		ex_ni
+# define ex_interface		ex_ni
 # define ex_finish		ex_ni
 # define ex_function		ex_ni
 # define ex_if			ex_ni
@@ -300,6 +303,7 @@
 # define ex_scriptnames		ex_ni
 # define ex_throw		ex_ni
 # define ex_try			ex_ni
+# define ex_type		ex_ni
 # define ex_unlet		ex_ni
 # define ex_while		ex_ni
 # define ex_import		ex_ni
@@ -6693,12 +6697,13 @@
 }
 
 /*
- * Command modifier used in a wrong way.
+ * Command modifier used in a wrong way.  Also for other commands that can't
+ * appear at the toplevel.
  */
     static void
 ex_wrongmodifier(exarg_T *eap)
 {
-    eap->errmsg = _(e_invalid_command);
+    eap->errmsg = ex_errmsg(e_invalid_command_str, eap->cmd);
 }
 
 /*
diff --git a/src/proto.h b/src/proto.h
index 9d1e134..50802ce 100644
--- a/src/proto.h
+++ b/src/proto.h
@@ -215,6 +215,7 @@
 # ifdef FEAT_EVAL
 // include vim9.h here, the types defined there are used by function arguments.
 #  include "vim9.h"
+#  include "vim9class.pro"
 #  include "vim9cmds.pro"
 #  include "vim9compile.pro"
 #  include "vim9execute.pro"
diff --git a/src/proto/vim9class.pro b/src/proto/vim9class.pro
new file mode 100644
index 0000000..4e55178
--- /dev/null
+++ b/src/proto/vim9class.pro
@@ -0,0 +1,6 @@
+/* vim9class.c */
+void ex_class(exarg_T *eap);
+void ex_interface(exarg_T *eap);
+void ex_enum(exarg_T *eap);
+void ex_type(exarg_T *eap);
+/* vim: set ft=c : */
diff --git a/src/testdir/test_cmdmods.vim b/src/testdir/test_cmdmods.vim
index d5a4e93..323a78e 100644
--- a/src/testdir/test_cmdmods.vim
+++ b/src/testdir/test_cmdmods.vim
@@ -15,6 +15,16 @@
   lines = getline(top, bot)
   var mods = lines->map((_, v) => substitute(v, '.*"\(\k*\)".*', '\1', ''))
 
+  # Add the other commands that use ex_wrongmodifier.
+  mods->extend([
+                'endclass',
+                'endenum',
+                'endinterface',
+                'public',
+                'static',
+                'this',
+              ])
+
   # Check the lists are equal.  Convert them to a dict to get a clearer error
   # message.
   var cmds_dict = {}
diff --git a/src/version.c b/src/version.c
index 10db247..68f2470 100644
--- a/src/version.c
+++ b/src/version.c
@@ -696,6 +696,8 @@
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    1001,
+/**/
     1000,
 /**/
     999,
diff --git a/src/vim9class.c b/src/vim9class.c
new file mode 100644
index 0000000..b2307cb
--- /dev/null
+++ b/src/vim9class.c
@@ -0,0 +1,110 @@
+/* vi:set ts=8 sts=4 sw=4 noet:
+ *
+ * VIM - Vi IMproved	by Bram Moolenaar
+ *
+ * Do ":help uganda"  in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+/*
+ * vim9class.c: Vim9 script class support
+ */
+
+#define USING_FLOAT_STUFF
+#include "vim.h"
+
+#if defined(FEAT_EVAL) || defined(PROTO)
+
+// When not generating protos this is included in proto.h
+#ifdef PROTO
+# include "vim9.h"
+#endif
+
+/*
+ * Handle ":class" and ":abstract class" up to ":endclass".
+ */
+    void
+ex_class(exarg_T *eap)
+{
+    int is_abstract = eap->cmdidx == CMD_abstract;
+
+    char_u *arg = eap->arg;
+    if (is_abstract)
+    {
+	if (STRNCMP(arg, "class", 5) != 0 || !VIM_ISWHITE(arg[5]))
+	{
+	    semsg(_(e_invalid_argument_str), arg);
+	    return;
+	}
+	arg = skipwhite(arg + 5);
+    }
+
+    if (!ASCII_ISUPPER(*arg))
+    {
+	semsg(_(e_class_name_must_start_with_uppercase_letter_str), arg);
+	return;
+    }
+
+    // TODO:
+    // generics: <Tkey, Tentry>
+    //    extends SomeClass
+    //    implements SomeInterface
+    //    specifies SomeInterface
+
+
+    // TODO: handle until "endclass" is found:
+    // object and class members (public, read access, private):
+    //	  public this.varname
+    //	  public static varname
+    //	  this.varname
+    //	  static varname
+    //	  this._varname
+    //	  static _varname
+    //
+    // constructors:
+    //	  def new()
+    //	  enddef
+    //	  def newOther()
+    //	  enddef
+    //
+    // methods (object, class, generics):
+    //	  def someMethod()
+    //	  enddef
+    //	  static def someMethod()
+    //	  enddef
+    //	  def <Tval> someMethod()
+    //	  enddef
+    //	  static def <Tval> someMethod()
+    //	  enddef
+}
+
+/*
+ * Handle ":interface" up to ":endinterface".
+ */
+    void
+ex_interface(exarg_T *eap UNUSED)
+{
+    // TODO
+}
+
+/*
+ * Handle ":enum" up to ":endenum".
+ */
+    void
+ex_enum(exarg_T *eap UNUSED)
+{
+    // TODO
+}
+
+/*
+ * Handle ":type".
+ */
+    void
+ex_type(exarg_T *eap UNUSED)
+{
+    // TODO
+}
+
+
+#endif // FEAT_EVAL