Patch 9.0.1001
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.
Files:      Filelist, runtime/doc/vim9.txt, runtime/doc/vim9class.txt,
            runtime/doc/Makefile, src/ex_cmds.h, src/ex_cmdidxs.h,
            src/vim9class.c, src/proto/vim9class.pro, src/proto.h,
            src/ex_docmd.c, src/errors.h, src/Makefile, src/Make_ami.mak,
            src/Make_mvc.mak, src/Make_vms.mms, src/Make_cyg_ming.mak,
            src/testdir/test_cmdmods.vim


*** ../vim-9.0.1000/Filelist    2022-12-02 13:20:16.464758265 +0000
--- Filelist    2022-12-04 14:38:16.840614369 +0000
***************
*** 163,168 ****
--- 163,169 ----
                src/version.h \
                src/vim.h \
                src/vim9.h \
+               src/vim9class.c \
                src/vim9cmds.c \
                src/vim9compile.c \
                src/vim9execute.c \
***************
*** 327,332 ****
--- 328,334 ----
                src/proto/usercmd.pro \
                src/proto/userfunc.pro \
                src/proto/version.pro \
+               src/proto/vim9class.pro \
                src/proto/vim9cmds.pro \
                src/proto/vim9compile.pro \
                src/proto/vim9execute.pro \
*** ../vim-9.0.1000/runtime/doc/vim9.txt        2022-10-11 21:51:09.962103580 
+0100
--- runtime/doc/vim9.txt        2022-12-03 21:49:26.591652433 +0000
***************
*** 16,22 ****
  3.  New style functions                       |fast-functions|
  4.  Types                             |vim9-types|
  5.  Namespace, Import and Export      |vim9script|
! 6.  Future work: classes              |vim9-classes|
  
  9.  Rationale                         |vim9-rationale|
  
--- 16,22 ----
  3.  New style functions                       |fast-functions|
  4.  Types                             |vim9-types|
  5.  Namespace, Import and Export      |vim9script|
! 6.  Classes and interfaces            |vim9-classes|
  
  9.  Rationale                         |vim9-rationale|
  
***************
*** 1940,2003 ****
  
  ==============================================================================
  
! 6. Future work: classes                                       *vim9-classes*
  
! Above "class" was mentioned a few times, but it has not been implemented yet.
! Most of Vim9 script can be created without this functionality, and since
! implementing classes is going to be a lot of work, it is left for the future.
! For now we'll just make sure classes can be added later.
! 
! Thoughts:
! - `class` / `endclass`, the whole class must be in one file
! - Class names are always CamelCase (to avoid a name clash with builtin types)
! - A single constructor called "constructor"
! - Single inheritance with `class ThisClass extends BaseClass`
! - `abstract class` (class with incomplete implementation)
! - `interface` / `endinterface` (abstract class without any implementation)
! - `class SomeClass implements SomeInterface`
! - Generics for class: `class <Tkey, Tentry>`
! - Generics for function: `def <Tkey> GetLast(key: Tkey)`
! 
! Again, much of this is from TypeScript with a slightly different syntax.
! 
! Some things that look like good additions:
! - Use a class as an interface (like Dart)
! - Extend a class with methods, using an import (like Dart)
! - Mixins
! - For testing: Mock mechanism
! 
! An important class that will be provided is "Promise".  Since Vim is single
! threaded, connecting asynchronous operations is a natural way of allowing
! plugins to do their work without blocking the user.  It's a uniform way to
! invoke callbacks and handle timeouts and errors.
! 
! Some commands have already been reserved:
!       *:class*
!       *:endclass*
!       *:abstract*
!       *:enum*
!       *:endenum*
!       *:interface*
!       *:endinterface*
!       *:static*
!       *:type*
! 
! Some examples: >
! 
!       abstract class Person 
!           static const prefix = 'xxx'
!           var name: string
!           
!           def constructor(name: string)
!               this.name = name
!           enddef
! 
!           def display(): void
!               echo name
!           enddef
  
-           abstract def find(string): Person
-       endclass
  
  ==============================================================================
  
--- 1940,1956 ----
  
  ==============================================================================
  
! 6. Classes and interfaces                             *vim9-classes*
  
! In legacy script a Dictionary could be used as a kind-of object, by adding
! members that are functions.  However, this is quite inefficient and requires
! the writer to do the work of making sure all the objects have the right
! members.  See |Dictionary-function|.
! 
! In |Vim9| script you can have classes, objects and interfaces like in most
! popular object-oriented programming languages.  Since this is a lot of
! functionality it is located in a separate help file: |vim9class.txt|.
  
  
  ==============================================================================
  
***************
*** 2284,2301 ****
  support for classes in Vim is then a problem.
  
  
- Classes ~
- 
- Vim supports a kind-of object oriented programming by adding methods to a
- dictionary.  With some care this can be made to work, but it does not look
- like real classes.  On top of that, it's quite slow, because of the use of
- dictionaries.
- 
- It would be good to support real classes, and this is planned for a later
- version.  The support is a "minimal common functionality" of class support in
- most languages.  It will work much like Java, which is the most popular
- programming language.
- 
- 
  
   vim:tw=78:ts=8:noet:ft=help:norl:
--- 2237,2241 ----
*** ../vim-9.0.1000/runtime/doc/vim9class.txt   2022-12-04 20:08:19.507852383 
+0000
--- runtime/doc/vim9class.txt   2022-12-04 20:02:27.131855358 +0000
***************
*** 0 ****
--- 1,697 ----
+ *vim9class.txt*       For Vim version 9.0.  Last change: 2022 Dec 04
+ 
+ 
+                 VIM REFERENCE MANUAL    by Bram Moolenaar
+ 
+ 
+ NOTE - This is under development, anything can still change! - NOTE
+ 
+ 
+ Vim9 classes, objects, interfaces, types and enums.
+ 
+ 1.  Overview                  |Vim9-class-overview|
+ 2.  A simple class            |Vim9-simple-class|
+ 3.  Using an abstract class   |Vim9-abstract-class|
+ 4.  Using an interface                |Vim9-using-interface|
+ 5.  More class details                |Vim9-class|
+ 6.  Type definition           |Vim9-type|
+ 7.  Enum                      |Vim9-enum|
+ 
+ 9.  Rationale
+ 10. To be done later
+ 
+ ==============================================================================
+ 
+ 1. Overview                                   *Vim9-class-overview*
+ 
+ The fancy term is "object-oriented programming".  You can find lots of study
+ material about this subject.  Here we document what |Vim9| script provides,
+ assuming you know the basics already.  Added are helpful hints about how
+ to use this functionality effectively.
+ 
+ The basic item is an object:
+ - An object stores state.  It contains one or more variables that can each
+   have a value.
+ - An object usually provides functions that manipulate its state.  These
+   functions are invoked "on the object", which is what sets it apart from the
+   traditional separation of data and code that manipulates the data.
+ - An object has a well defined interface, with typed member variables and
+   member functions.
+ - Objects are created by a class and all objects have the same interface.
+   This never changes, it is not dynamic.
+ 
+ An object can only be created by a class.  A class provides:
+ - A new() method, the constructor, which returns an object for the class.
+   This method is invoked on the class name: MyClass.new().
+ - State shared by all objects of the class: class variables and constants.
+ - A hierarchy of classes, with super-classes and sub-classes, inheritance.
+ 
+ An interface is used to specify properties of an object:
+ - An object can declare several interfaces that it implements.
+ - Different objects implementing the same interface can be used the same way.
+ 
+ The class hierarchy allows for single inheritance.  Otherwise interfaces are
+ to be used where needed.
+ 
+ 
+ Class modeling ~
+ 
+ You can model classes any way you like.  Keep in mind what you are building,
+ don't try to model the real world.  This can be confusing, especially because
+ teachers use real-world objects to explain class relations and you might think
+ your model should therefore reflect the real world.  It doesn't!  The model
+ should match your purpose.
+ 
+ You will soon find that composition is often better than inheritance.  Don't
+ waste time trying to find the optimal class model.  Or waste time discussing
+ whether a square is a rectangle or that a rectangle is a square.  It doesn't
+ matter.
+ 
+ 
+ ==============================================================================
+ 
+ 2.  A simple class                            *Vim9-simple-class*
+ 
+ Let's start with a simple example: a class that stores a text position: >
+ 
+       class TextPosition
+          this.lnum: number
+          this.col: number
+ 
+          def new(lnum: number, col: number)
+             this.lnum = lnum
+             this.col = col
+          enddef
+ 
+          def SetLnum(lnum: number)
+             this.lnum = lnum
+          enddef
+ 
+          def SetCol(col: number)
+             this.col = col
+          enddef
+ 
+          def SetPosition(lnum: number, col: number)
+             this.lnum = lnum
+             this.col = col
+          enddef
+        endclass
+ 
+ You can create an object from this class with the new() method: >
+ 
+       var pos = TextPosition.new(1, 1)
+ 
+ The object members "lnum" and "col" can be accessed directly: >
+ 
+       echo $'The text position is ({pos.lnum}, {pos.col})'
+ 
+ If you have been using other object-oriented languages you will notice that
+ in Vim the object members are consistently referred to with the "this."
+ prefix.  This is different from languages like Java and TypeScript.  This
+ naming convention makes the object members easy to spot.  Also, when a
+ variable does not have the "this." prefix you know it is not an object member.
+ 
+ 
+ Member write access ~
+ 
+ Now try to change an object member directly: >
+ 
+       pos.lnum = 9
+ 
+ This will give you an error!  That is because by default object members can be
+ read but not set.  That's why the class provides a method for it: >
+ 
+       pos.SetLnum(9)
+ 
+ Allowing to read but not set an object member is the most common and safest
+ way.  Most often there is no problem using a value, while setting a value may
+ have side effects that need to be taken care of.  In this case, the SetLnum()
+ method could check if the line number is valid and either give an error or use
+ the closest valid value.
+ 
+ If you don't care about side effects and want to allow the object member to be
+ changed at any time, you can make it public: >
+ 
+       public this.lnum: number
+       public this.col number
+ 
+ Now you don't need the SetLnum(), SetCol() and SetPosition() methods, setting
+ "pos.lnum" directly above will no longer give an error.
+ 
+ 
+ Private members ~
+ 
+ On the other hand, if you do not want the object members to be read directly,
+ you can make them private.  This is done by prefixing an underscore to the
+ name: >
+ 
+       this._lnum: number
+       this._col number
+ 
+ Now you need to provide methods to get the value of the private members.
+ These are commonly call getters.  We recommend using a name that starts with
+ "Get": >
+ 
+       def GetLnum(): number
+          return this._lnum
+       enddef
+ 
+       def GetCol() number
+          return this._col
+       enddef
+ 
+ This example isn't very useful, the members might as well have been public.
+ It does become useful if you check the value.  For example, restrict the line
+ number to the total number of lines: >
+ 
+       def GetLnum(): number
+          if this._lnum > this._lineCount
+             return this._lineCount
+          endif
+          return this._lnum
+       enddef
+ 
+ 
+ Simplifying the new() method ~
+ 
+ Many constructors take values for the object members.  Thus you very often see
+ this pattern: >
+ 
+          this.lnum: number
+          this.col: number
+ 
+          def new(lnum: number, col: number)
+             this.lnum = lnum
+             this.col = col
+          enddef
+ 
+ Not only is this text you need to write, it also has the type of each member
+ twice.  Since this is so common a shorter way to write new() is provided: >
+ 
+          def new(this.lnum, this.col)
+          enddef
+ 
+ The semantics are easy to understand: Providing the object member name,
+ including "this.", as the argument to new() means the value provided in the
+ new() call is assigned to that object member.  This mechanism is coming from
+ the Dart language.
+ 
+ The sequence of constructing a new object is:
+ 1. Memory is allocated and cleared.  All values are zero/false/empty.
+ 2. For each declared member that has an initializer, the expression is
+    evaluated and assigned to the member.  This happens in the sequence the
+    members are declared in the class.
+ 3. Arguments in the new() method in the "this.name" form are assigned.
+ 4. The body of the new() method is executed.
+ 
+ TODO: for a sub-class the constructor of the parent class will be invoked
+ somewhere.
+ 
+ 
+ ==============================================================================
+ 
+ 3.  Using an abstract class                   *Vim9-abstract-class*
+ 
+ An abstract class forms the base for at least one sub-class.  In the class
+ model one often finds that a few classes have the same properties that can be
+ shared, but a class with those properties does not have enough state to create
+ an object from.  A sub-class must extend the abstract class and add the
+ missing state and/or methods before it can be used to create objects for.
+ 
+ An abstract class does not have a new() method.
+ 
+ For example, a Shape class could store a color and thickness.  You cannot
+ create a Shape object, it is missing the information about what kind of shape
+ it is.  The Shape class functions as the base for a Square and a Triangle
+ class, for which objects can be created.  Example: >
+ 
+       abstract class Shape
+          this.color = Color.Black
+          this.thickness = 10
+       endclass
+ 
+       class Square extends Shape
+          this.size: number
+ 
+          def new(this.size)
+          enddef
+       endclass
+ 
+       class Triangle extends Shape
+          this.base: number
+          this.height: number
+ 
+          def new(this.base, this.height)
+          enddef
+       endclass
+ <
+                                               *class-member* *:static*
+ Class members are declared with "static".  They are used by the name without a
+ prefix: >
+ 
+       class OtherThing
+          this.size: number
+          static totalSize: number
+ 
+          def new(this.size)
+             totalSize += this.size
+          enddef
+       endclass
+ <
+                                               *class-method*
+ Class methods are also declared with "static".  They have no access to object
+ members, they cannot use the "this" keyword. >
+ 
+       class OtherThing
+          this.size: number
+          static totalSize: number
+ 
+          " Clear the total size and return the value it had before. 
+          static def ClearTotalSize(): number
+             var prev = totalSize
+             totalSize = 0
+             return prev
+          enddef
+       endclass
+ 
+ 
+ ==============================================================================
+ 
+ 4.  Using an interface                                *Vim9-using-interface*
+ 
+ The example above with Shape, Square and Triangle can be made more useful if
+ we add a method to compute the surface of the object.  For that we create the
+ interface called HasSurface, which specifies one method Surface() that returns
+ a number.  This example extends the one above: >
+ 
+       abstract class Shape
+          this.color = Color.Black
+          this.thickness = 10
+       endclass
+ 
+       interface HasSurface
+          def Surface(): number
+       endinterface
+ 
+       class Square extends Shape implements HasSurface
+          this.size: number
+ 
+          def new(this.size)
+          enddef
+ 
+          def Surface(): number
+             return this.size * this.size
+          enddef
+       endclass
+ 
+       class Triangle extends Shape implements HasSurface
+          this.base: number
+          this.height: number
+ 
+          def new(this.base, this.height)
+          enddef
+ 
+          def Surface(): number
+             return this.base * this.height / 2
+          enddef
+       endclass
+ 
+ The interface name can be used as a type: >
+ 
+       var shapes: list<HasSurface> = [
+                               Square.new(12),
+                               Triangle.new(8, 15),
+                               ]
+       for shape in shapes
+          echo $'the surface is {shape.Surface()}'
+       endfor
+ 
+ 
+ ==============================================================================
+ 
+ 5.  More class details                                        *Vim9-class*
+ 
+ Defining a class ~
+                                       *:class* *:endclass* *:abstract*
+ A class is defined between `:class` and `:endclass`.  The whole class is
+ defined in one script file.  It is not possible to add to a class later.
+ 
+ It is possible to define more than one class in a script file.  Although it
+ usually is better to export only one main class.  It can be useful to define
+ types, enums and helper classes though.
+ 
+ The `:abstract` keyword may be prefixed and `:export` may be used.  That gives
+ these variants: >
+ 
+       class ClassName
+       endclass
+ 
+       export class ClassName
+       endclass
+ 
+       abstract class ClassName
+       endclass
+ 
+       export abstract class ClassName
+       endclass
+ <
+                                                       *E1314*
+ The class name should be CamelCased.  It must start with an uppercase letter.
+ That avoids clashing with builtin types.
+ 
+ After the class name these optional items can be used.  Each can appear only
+ once.  They can appear in any order, although this order is recommended: >
+       extends ClassName
+       implements InterfaceName, OtherInterface
+       specifies SomeInterface
+ <                                                     *extends*
+ A class can extend one other class.
+                                                       *implements*
+ A class can implement one or more interfaces.
+                                                       *specifies*
+ A class can declare it's interface, the object members and methods, with a
+ named interface.  This avoids the need for separately specifying the
+ interface, which is often done an many languages, especially Java.
+ 
+ 
+ Defining an interface ~
+                                               *:interface* *:endinterface*
+ An interface is defined between `:interface` and `:endinterface`.  It may be
+ prefixed with `:export`: >
+ 
+       interface InterfaceName
+       endinterface
+ 
+       export interface InterfaceName
+       endinterface
+ 
+ An interface can declare object members, just like in a class but without any
+ initializer.
+ 
+ An interface can declare methods with `:def`, including the arguments and
+ return type, but without the body and without `:enddef`.  Example: >
+ 
+       interface HasSurface
+          this.size: number
+          def Surface(): number
+       endinterface
+ 
+ The "Has" prefix can be used to make it easier to guess this is an interface
+ name, with a hint about what it provides.
+ 
+ 
+ Default constructor ~
+ 
+ In case you define a class without a new() method, one will be automatically
+ defined.  This default constructor will have arguments for all the object
+ members, in the order they were specified.  Thus if your class looks like: >
+ 
+       class AutoNew
+          this.name: string
+          this.age: number
+          this.gender: Gender
+       endclass
+ 
+ Then The default constructor will be: >
+ 
+       def new(this.name, this.age, this.gender)
+       enddef
+ 
+ All object members will be used, also private access ones.
+ 
+ 
+ Multiple constructors ~
+ 
+ Normally a class has just one new() constructor.  In case you find that the
+ constructor is often called with the same arguments you may want to simplify
+ your code by putting those arguments into a second constructor method.  For
+ example, if you tend to use the color black a lot: >
+ 
+       def new(this.garment, this.color, this.size)
+       enddef
+       ...
+       var pants = new(Garment.pants, Color.black, "XL")
+       var shirt = new(Garment.shirt, Color.black, "XL")
+       var shoes = new(Garment.shoes, Color.black, "45")
+ 
+ Instead of repeating the color every time you can add a constructor that
+ includes it: >
+ 
+       def newBlack(this.garment, this.size)
+          this.color = Color.black
+       enddef
+       ...
+       var pants = newBlack(Garment.pants, "XL")
+       var shirt = newBlack(Garment.shirt, "XL")
+       var shoes = newBlack(Garment.shoes, "9.5")
+ 
+ Note that the method name must start with "new".  If there is no method called
+ "new()" then the default constructor is added, even though there are other
+ constructor methods.
+ 
+ 
+ ==============================================================================
+ 
+ 6.  Type definition                                   *Vim9-type* *:type*
+ 
+ A type definition is giving a name to a type specification.  For Example: >
+ 
+       :type ListOfStrings list<string>
+ 
+ TODO: more explanation
+ 
+ 
+ ==============================================================================
+ 
+ 7.  Enum                                      *Vim9-enum* *:enum* *:endenum*
+ 
+ An enum is a type that can have one of a list of values.  Example: >
+ 
+       :enum Color
+               White
+               Red
+               Green
+               Blue
+               Black
+       :endenum
+ 
+ TODO: more explanation
+ 
+ 
+ ==============================================================================
+ 
+ 9.  Rationale
+ 
+ Most of the choices for |Vim9| classes come from popular and recently
+ developed languages, such as Java, TypeScript and Dart.  The syntax has been
+ made to fit with the way Vim script works, such as using `endclass` instead of
+ using curly braces around the whole class.
+ 
+ Some common constructs of object-oriented languages were chosen very long ago
+ when this kind of programming was still new, and later found to be
+ sub-optimal.  By this time those constructs were widely used and changing them
+ was not an option.  In Vim we do have the freedom to make different choices,
+ since classes are completely new.  We can make the syntax simpler and more
+ consistent than what "old" languages use.  Without diverting too much, it
+ should still mostly look like what you know from existing languages.
+ 
+ Some recently developed languages add all kinds of fancy features that we
+ don't need for Vim.  But some have nice ideas that we do want to use.
+ Thus we end up with a base of what is common in popular languages, dropping
+ what looks like a bad idea, and adding some nice features that are easy to
+ understand.
+ 
+ The main rules we use to make decisions:
+ - Keep it simple.
+ - No surprises, mostly do what other languages are doing.
+ - Avoid mistakes from the past.
+ - Avoid the need for the script writer to consult the help to understand how
+   things work, most things should be obvious.
+ - Keep it consistent.
+ - Aim at an average size plugin, not at a huge project.
+ 
+ 
+ Using new() for the constructor ~
+ 
+ Many languages use the class name for the constructor method.  A disadvantage
+ is that quite often this is a long name.  And when changing the class name all
+ constructor methods need to be renamed.  Not a big deal, but still a
+ disadvantage.
+ 
+ Other languages, such as TypeScript, use a specific name, such as
+ "constructor()".  That seems better.  However, using "new" or "new()" to
+ create a new object has no obvious relation with "constructor()".
+ 
+ For |Vim9| script using the same method name for all constructors seemed like
+ the right choice, and by calling it new() the relation between the caller and
+ the method being called is obvious.
+ 
+ 
+ No overloading of the constructor ~
+ 
+ In Vim script, both legacy and |Vim9| script, there is no overloading of
+ functions.  That means it is not possible to use the same function name with
+ different types of arguments.  Therefore there also is only one new()
+ constructor.
+ 
+ With |Vim9| script it would be possible to support overloading, since
+ arguments are typed.  However, this gets complicated very quickly.  Looking at
+ a new() call one has to inspect the types of the arguments to know which of
+ several new() methods is actually being called.  And that can require
+ inspecting quite a bit of code.  For example, if one of the arguments is the
+ return value of a method, you need to find that method to see what type it is
+ returning.
+ 
+ Instead, every constructor has to have a different name, starting with "new".
+ That way multiple constructors with different arguments are possible, while it
+ is very easy to see which constructor is being used.  And the type of
+ arguments can be properly checked.
+ 
+ 
+ No overloading of methods ~
+ 
+ Same reasoning as for the constructor: It is often not obvious what type
+ arguments have, which would make it difficult to figure out what method is
+ actually being called.  Better just give the methods a different name, then
+ type checking will make sure it works as you intended.  This rules out
+ polymorphism, which we don't really need anyway.
+ 
+ 
+ Using "this.member" everywhere ~
+ 
+ The object members in various programming languages can often be accessed in
+ different ways, depending on the location.  Sometimes "this." has to be
+ prepended to avoid ambiguity.  They are usually declared without "this.".
+ That is quite inconsistent and sometimes confusing.
+ 
+ A very common issue is that in the constructor the arguments use the same name
+ as the object member.  Then for these members "this." needs to be prefixed in
+ the body, while for other members this is not needed and often omitted.  This
+ leads to a mix of members with and without "this.", which is inconsistent.
+ 
+ For |Vim9| classes the "this." prefix is always used.  Also for declaring the
+ members.  Simple and consistent.  When looking at the code inside a class it's
+ also directly clear which variable references are object members and which
+ aren't.
+ 
+ 
+ Single inheritance and interfaces ~
+ 
+ Some languages support multiple inheritance.  Although that can be useful in
+ some cases, it makes the rules of how a class works quite complicated.
+ Instead, using interfaces to declare what is supported is much simpler.  The
+ very popular Java language does it this way, and it should be good enough for
+ Vim.  The "keep it simple" rule applies here.  
+ 
+ Explicitly declaring that a class supports an interface makes it easy to see
+ what a class is intended for.  It also makes it possible to do proper type
+ checking.  When an interface is changed any class that declares to implement
+ it will be checked if that change was also changed.  The mechanism to assume a
+ class implements an interface just because the methods happen to match is
+ brittle and leads to obscure problems, let's not do that.
+ 
+ 
+ Using class members ~
+ 
+ Using "static member" to declare a class member is very common, nothing new
+ here.  In |Vim9| script these can be accessed directly by their name.  Very
+ much like how a script-local variable can be used in a function.  Since object
+ members are always accessed with "this." prepended, it's also quickly clear
+ what kind of member it is.
+ 
+ TypeScript prepends the class name before the class member, also inside the
+ class.  This has two problems: The class name can be rather long, taking up
+ quite a bit of space, and when the class is renamed all these places need to
+ be changed too.
+ 
+ 
+ Using "ClassName.new()" to construct an object ~
+ 
+ Many languages use the "new" operator to create an object, which is actually
+ kind of strange, since the constructor is defined as a method with arguments,
+ not a command.  TypeScript also has the "new" keyword, but the method is
+ called "constructor()", it is hard to see the relation between the two.
+ 
+ In |Vim9| script the constructor method is called new(), and it is invoked as
+ new(), simple and straightforward.  Other languages use "new ClassName()",
+ while there is no ClassName() method, it's a method by another name in the
+ class called ClassName.  Quite confusing.
+ 
+ 
+ Default read access to object members ~
+ 
+ Some users will remark that the access rules for object members are
+ asymmetric.  Well, that is intentional.  Changing a value is a very different
+ action than reading a value.  The read operation has no side effects, it can
+ be done any number of times without affecting the object.  Changing the value
+ can have many side effects, and even have a ripple effect, affecting other
+ objects.
+ 
+ When adding object members one usually doesn't think much about this, just get
+ the type right.  And normally the values are set in the new() method.
+ Therefore defaulting to read access only "just works" in most cases.  And when
+ directly writing you get an error, which makes you wonder if you actually want
+ to allow that.  This helps writing code with fewer mistakes.
+ 
+ 
+ Making object membes private with an underscore ~
+ 
+ When an object member is private, it can only be read and changed inside the
+ class (and in sub-classes), then it cannot be used outside of the class.
+ Prepending an underscore is a simple way to make that visible.  Various
+ programming languages have this as a recommendation.
+ 
+ In case you change your mind and want to make the object member accessible
+ outside of the class, you will have to remove the underscore everywhere.
+ Since the name only appears in the class (and sub-classes) they will be easy
+ to find and change.
+ 
+ The other way around is much harder: you can easily prepend an underscore to
+ the object member inside the class to make it private, but any usage elsewhere
+ you will have to track down and change.  You may have to make it a "set"
+ method call.  This reflects the real world problem that taking away access
+ requires work to be done for all places where that access exists.
+ 
+ An alternative would have been using the "private" keyword, just like "public"
+ changes the access in the other direction.  Well, that's just to reduce the
+ number of keywords.
+ 
+ 
+ No protected object members ~
+ 
+ Some languages provide several ways to control access to object members.  The
+ most known is "protected", and the meaning varies from language to language.
+ Others are "shared", "private" and even "friend".
+ 
+ These rules make life more difficult.  That can be justified in projects where
+ many people work on the same, complex code where it is easy to make mistakes.
+ Especially when refactoring or other changes to the class model.
+ 
+ The Vim scripts are expected to be used in a plugin, with just one person or a
+ small team working on it.  Complex rules then only make it more complicated,
+ the extra safety provide by the rules isn't really needed.  Let's just keep it
+ simple and not specify access details.
+ 
+ 
+ ==============================================================================
+ 
+ 10. To be done later
+ 
+ Can a newSomething() constructor invoke another constructor?  If yes, what are
+ the restrictions?
+ 
+ Thoughts:
+ - Generics for a class: `class <Tkey, Tentry>`
+ - Generics for a function: `def <Tkey> GetLast(key: Tkey)`
+ - Mixins: not sure if that is useful, leave out for simplicity.
+ 
+ Some things that look like good additions:
+ - For testing: Mock mechanism
+ 
+ An important class to be provided is "Promise".  Since Vim is single
+ threaded, connecting asynchronous operations is a natural way of allowing
+ plugins to do their work without blocking the user.  It's a uniform way to
+ invoke callbacks and handle timeouts and errors.
+ 
+ 
+  vim:tw=78:ts=8:noet:ft=help:norl:
*** ../vim-9.0.1000/runtime/doc/Makefile        2022-05-13 12:03:04.000000000 
+0100
--- runtime/doc/Makefile        2022-12-03 22:18:13.326975383 +0000
***************
*** 113,118 ****
--- 115,121 ----
        todo.txt \
        uganda.txt \
        undo.txt \
+       userfunc.txt \
        usr_01.txt \
        usr_02.txt \
        usr_03.txt \
***************
*** 158,163 ****
--- 161,167 ----
        version9.txt \
        vi_diff.txt \
        vim9.txt \
+       vim9class.txt \
        visual.txt \
        windows.txt \
        workshop.txt
***************
*** 261,266 ****
--- 267,273 ----
        todo.html \
        uganda.html \
        undo.html \
+       userfunc.html \
        usr_01.html \
        usr_02.html \
        usr_03.html \
***************
*** 307,312 ****
--- 314,320 ----
        vi_diff.html \
        vimindex.html \
        vim9.html \
+       vim9class.html \
        visual.html \
        windows.html \
        workshop.html
*** ../vim-9.0.1000/src/ex_cmds.h       2022-10-07 17:26:19.023293895 +0100
--- src/ex_cmds.h       2022-12-04 17:11:19.528621148 +0000
***************
*** 126,132 ****
  EXCMD(CMD_aboveleft,  "aboveleft",    ex_wrongmodifier,
        EX_NEEDARG|EX_EXTRA|EX_NOTRLCOM,
        ADDR_NONE),
! EXCMD(CMD_abstract,   "abstract",     ex_ni,
        EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
        ADDR_NONE),
  EXCMD(CMD_all,                "all",          ex_all,
--- 126,132 ----
  EXCMD(CMD_aboveleft,  "aboveleft",    ex_wrongmodifier,
        EX_NEEDARG|EX_EXTRA|EX_NOTRLCOM,
        ADDR_NONE),
! EXCMD(CMD_abstract,   "abstract",     ex_class,
        EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
        ADDR_NONE),
  EXCMD(CMD_all,                "all",          ex_all,
***************
*** 354,360 ****
  EXCMD(CMD_clast,      "clast",        ex_cc,
        EX_RANGE|EX_COUNT|EX_TRLBAR|EX_BANG,
        ADDR_UNSIGNED),
! EXCMD(CMD_class,      "class",        ex_ni,
        EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK|EX_EXPORT,
        ADDR_NONE),
  EXCMD(CMD_close,      "close",        ex_close,
--- 354,360 ----
  EXCMD(CMD_clast,      "clast",        ex_cc,
        EX_RANGE|EX_COUNT|EX_TRLBAR|EX_BANG,
        ADDR_UNSIGNED),
! 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,582 ****
  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,
        EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
        ADDR_NONE),
! EXCMD(CMD_endclass,   "endclass",     ex_ni,
        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,
        EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
        ADDR_NONE),
  EXCMD(CMD_endfunction,        "endfunction",  ex_endfunction,
--- 567,582 ----
  EXCMD(CMD_endif,      "endif",        ex_endif,
        EX_TRLBAR|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK|EX_WHOLE,
        ADDR_NONE),
! EXCMD(CMD_endinterface,       "endinterface", ex_wrongmodifier,
        EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
        ADDR_NONE),
! 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_wrongmodifier,
        EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
        ADDR_NONE),
  EXCMD(CMD_endfunction,        "endfunction",  ex_endfunction,
***************
*** 594,600 ****
  EXCMD(CMD_enew,               "enew",         ex_edit,
        EX_BANG|EX_TRLBAR,
        ADDR_NONE),
! EXCMD(CMD_enum,               "enum",         ex_ni,
        EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK|EX_EXPORT,
        ADDR_NONE),
  EXCMD(CMD_eval,               "eval",         ex_eval,
--- 594,600 ----
  EXCMD(CMD_enew,               "enew",         ex_edit,
        EX_BANG|EX_TRLBAR,
        ADDR_NONE),
! 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,762 ****
  EXCMD(CMD_intro,      "intro",        ex_intro,
        EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
        ADDR_NONE),
! EXCMD(CMD_interface,  "interface",    ex_ni,
        EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
        ADDR_NONE),
  EXCMD(CMD_isearch,    "isearch",      ex_findpat,
--- 756,762 ----
  EXCMD(CMD_intro,      "intro",        ex_intro,
        EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
        ADDR_NONE),
! EXCMD(CMD_interface,  "interface",    ex_interface,
        EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
        ADDR_NONE),
  EXCMD(CMD_isearch,    "isearch",      ex_findpat,
***************
*** 1215,1220 ****
--- 1215,1223 ----
  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,1494 ****
  EXCMD(CMD_startreplace,       "startreplace", ex_startinsert,
        EX_BANG|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
        ADDR_NONE),
! EXCMD(CMD_static,     "static",       ex_ni,
        EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
        ADDR_NONE),
  EXCMD(CMD_stopinsert, "stopinsert",   ex_stopinsert,
--- 1491,1497 ----
  EXCMD(CMD_startreplace,       "startreplace", ex_startinsert,
        EX_BANG|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
        ADDR_NONE),
! EXCMD(CMD_static,     "static",       ex_wrongmodifier,
        EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
        ADDR_NONE),
  EXCMD(CMD_stopinsert, "stopinsert",   ex_stopinsert,
***************
*** 1614,1619 ****
--- 1617,1625 ----
  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,1671 ****
  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,
        EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK|EX_EXPORT,
        ADDR_NONE),
  EXCMD(CMD_undo,               "undo",         ex_undo,
--- 1671,1677 ----
  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_type,
        EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK|EX_EXPORT,
        ADDR_NONE),
  EXCMD(CMD_undo,               "undo",         ex_undo,
*** ../vim-9.0.1000/src/ex_cmdidxs.h    2022-09-03 21:35:50.184158219 +0100
--- src/ex_cmdidxs.h    2022-12-04 15:39:24.835737128 +0000
***************
*** 21,36 ****
    /* 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
  };
  
  /*
--- 21,36 ----
    /* n */ 308,
    /* o */ 328,
    /* p */ 340,
!   /* q */ 380,
!   /* r */ 383,
!   /* s */ 403,
!   /* t */ 473,
!   /* u */ 520,
!   /* v */ 531,
!   /* w */ 552,
!   /* x */ 566,
!   /* y */ 576,
!   /* z */ 577
  };
  
  /*
***************
*** 56,66 ****
    /* 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 },
    /* 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 },
    /* 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 },
--- 56,66 ----
    /* 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, 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, 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,72 ****
    /* 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;
--- 69,72 ----
    /* 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 = 594;
*** ../vim-9.0.1000/src/vim9class.c     2022-12-04 20:08:19.523852382 +0000
--- src/vim9class.c     2022-12-04 17:10:26.100686606 +0000
***************
*** 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
*** ../vim-9.0.1000/src/proto/vim9class.pro     2022-12-04 20:08:19.527852383 
+0000
--- src/proto/vim9class.pro     2022-12-04 17:00:37.753590459 +0000
***************
*** 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 : */
*** ../vim-9.0.1000/src/proto.h 2022-11-30 20:20:52.751228273 +0000
--- src/proto.h 2022-12-04 14:33:39.324958458 +0000
***************
*** 215,220 ****
--- 215,221 ----
  # 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"
*** ../vim-9.0.1000/src/ex_docmd.c      2022-11-28 18:51:38.955571567 +0000
--- src/ex_docmd.c      2022-12-04 16:58:01.129631271 +0000
***************
*** 267,272 ****
--- 267,273 ----
  # 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,291 ****
  # define ex_endif             ex_ni
  # define ex_endtry            ex_ni
  # define ex_endwhile          ex_ni
  # define ex_eval              ex_ni
  # define ex_execute           ex_ni
- # define ex_incdec            ex_ni
  # define ex_finally           ex_ni
  # define ex_finish            ex_ni
  # define ex_function          ex_ni
  # define ex_if                        ex_ni
--- 283,294 ----
  # 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_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,305 ****
--- 303,309 ----
  # 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,6704 ****
  }
  
  /*
!  * Command modifier used in a wrong way.
   */
      static void
  ex_wrongmodifier(exarg_T *eap)
  {
!     eap->errmsg = _(e_invalid_command);
  }
  
  /*
--- 6697,6709 ----
  }
  
  /*
!  * 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 = ex_errmsg(e_invalid_command_str, eap->cmd);
  }
  
  /*
*** ../vim-9.0.1000/src/errors.h        2022-11-25 16:31:46.964606667 +0000
--- src/errors.h        2022-12-04 14:57:23.938237758 +0000
***************
*** 3345,3347 ****
--- 3345,3351 ----
        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
*** ../vim-9.0.1000/src/Makefile        2022-11-30 18:11:52.694904295 +0000
--- src/Makefile        2022-12-04 14:36:48.416718399 +0000
***************
*** 1584,1589 ****
--- 1585,1591 ----
        usercmd.c \
        userfunc.c \
        version.c \
+       vim9class.c \
        vim9cmds.c \
        vim9compile.c \
        vim9execute.c \
***************
*** 1741,1746 ****
--- 1743,1749 ----
        objects/usercmd.o \
        objects/userfunc.o \
        objects/version.o \
+       objects/vim9class.o \
        objects/vim9cmds.o \
        objects/vim9compile.o \
        objects/vim9execute.o \
***************
*** 1931,1936 ****
--- 1934,1940 ----
        usercmd.pro \
        userfunc.pro \
        version.pro \
+       vim9class.pro \
        vim9cmds.pro \
        vim9compile.pro \
        vim9execute.pro \
***************
*** 3489,3494 ****
--- 3493,3501 ----
  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,4173 ****
--- 4175,4185 ----
   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 \
*** ../vim-9.0.1000/src/Make_ami.mak    2022-11-30 18:11:52.694904295 +0000
--- src/Make_ami.mak    2022-12-04 14:37:12.024690186 +0000
***************
*** 174,179 ****
--- 174,180 ----
        userfunc.c \
        version.c \
        viminfo.c \
+       vim9class.c \
        vim9cmds.c \
        vim9compile.c \
        vim9execute.c \
*** ../vim-9.0.1000/src/Make_mvc.mak    2022-11-30 18:11:52.694904295 +0000
--- src/Make_mvc.mak    2022-12-04 14:37:52.456642607 +0000
***************
*** 735,740 ****
--- 735,741 ----
        $(OUTDIR)\undo.obj \
        $(OUTDIR)\usercmd.obj \
        $(OUTDIR)\userfunc.obj \
+       $(OUTDIR)\vim9class.obj \
        $(OUTDIR)\vim9cmds.obj \
        $(OUTDIR)\vim9compile.obj \
        $(OUTDIR)\vim9execute.obj \
***************
*** 1708,1713 ****
--- 1709,1716 ----
  
  $(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,1920 ****
--- 1918,1924 ----
        proto/undo.pro \
        proto/usercmd.pro \
        proto/userfunc.pro \
+       proto/vim9class.pro \
        proto/vim9cmds.pro \
        proto/vim9compile.pro \
        proto/vim9execute.pro \
*** ../vim-9.0.1000/src/Make_vms.mms    2022-11-30 18:11:52.694904295 +0000
--- src/Make_vms.mms    2022-12-04 14:38:47.272579548 +0000
***************
*** 409,414 ****
--- 409,415 ----
        usercmd.c \
        userfunc.c \
        version.c \
+       vim9class.c \
        vim9cmds.c \
        vim9compile.c \
        vim9execute.c \
***************
*** 534,539 ****
--- 535,541 ----
        usercmd.obj \
        userfunc.obj \
        version.obj \
+       vim9class.obj \
        vim9cmds.obj \
        vim9compile.obj \
        vim9execute.obj \
***************
*** 1122,1127 ****
--- 1124,1133 ----
   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 \
*** ../vim-9.0.1000/src/Make_cyg_ming.mak       2022-11-30 18:11:52.694904295 
+0000
--- src/Make_cyg_ming.mak       2022-12-04 14:39:13.456549960 +0000
***************
*** 851,856 ****
--- 851,857 ----
        $(OUTDIR)/usercmd.o \
        $(OUTDIR)/userfunc.o \
        $(OUTDIR)/version.o \
+       $(OUTDIR)/vim9class.o \
        $(OUTDIR)/vim9cmds.o \
        $(OUTDIR)/vim9compile.o \
        $(OUTDIR)/vim9execute.o \
***************
*** 1251,1256 ****
--- 1252,1259 ----
  
  $(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
*** ../vim-9.0.1000/src/testdir/test_cmdmods.vim        2022-11-02 
13:30:37.542314565 +0000
--- src/testdir/test_cmdmods.vim        2022-12-04 17:26:30.679877888 +0000
***************
*** 15,20 ****
--- 15,30 ----
    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 = {}
*** ../vim-9.0.1000/src/version.c       2022-12-03 18:35:04.248951287 +0000
--- src/version.c       2022-12-03 21:51:16.795575975 +0000
***************
*** 697,698 ****
--- 697,700 ----
  {   /* Add new patch number below this line */
+ /**/
+     1001,
  /**/

-- 
hundred-and-one symptoms of being an internet addict:
227. You sleep next to your monitor.  Or on top of it.

 /// 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/20221204201411.D08B51C06DC%40moolenaar.net.

Raspunde prin e-mail lui