Patch 8.2.1744
Problem:    Vim9: using ":const!" is weird.
Solution:   Use "var" - "final" - "const" like Dart.  "let" still works for
            now.
Files:      runtime/doc/vim9.txt, src/ex_cmds.h, src/errors.h, src/evalvars.c,
            src/proto/evalvars.pro, src/cmdexpand.c, src/eval.c,
            src/ex_docmd.c, src/vim9compile.c, src/vim9execute.c,
            src/vim9script.c, src/vim.h, src/ex_cmdidxs.h,
            src/testdir/test_vim9_assign.vim, src/testdir/test_vim9_script.vim


*** ../vim-8.2.1743/runtime/doc/vim9.txt        2020-09-14 21:38:47.752976295 
+0200
--- runtime/doc/vim9.txt        2020-09-26 13:48:50.326547733 +0200
***************
*** 19,24 ****
--- 19,25 ----
  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|
  
***************
*** 49,61 ****
  The Vim9 script syntax and semantics are used in:
  - a function defined with the `:def` command
  - a script file where the first command is `vim9script`
! - an autocommand defined in the context of these
  
  When using `:function` in a Vim9 script file the legacy syntax is used.
  However, this can be confusing and is therefore discouraged.
  
  Vim9 script and legacy Vim script can be mixed.  There is no requirement to
! rewrite old scripts, they keep working as before.
  
  ==============================================================================
  
--- 50,63 ----
  The Vim9 script syntax and semantics are used in:
  - a function defined with the `:def` command
  - a script file where the first command is `vim9script`
! - an autocommand defined in the context of the above
  
  When using `:function` in a Vim9 script file the legacy syntax is used.
  However, this can be confusing and is therefore discouraged.
  
  Vim9 script and legacy Vim script can be mixed.  There is no requirement to
! rewrite old scripts, they keep working as before.  You may want to use a few
! `:def` functions for code that needs to be fast.
  
  ==============================================================================
  
***************
*** 68,74 ****
  In legacy Vim script comments start with double quote.  In Vim9 script
  comments start with #. >
        # declarations
!       let count = 0  # number of occurrences
  
  The reason is that a double quote can also be the start of a string. In many
  places, especially halfway through an expression with a line break, it's hard
--- 70,76 ----
  In legacy Vim script comments start with double quote.  In Vim9 script
  comments start with #. >
        # declarations
!       var count = 0  # number of occurrences
  
  The reason is that a double quote can also be the start of a string. In many
  places, especially halfway through an expression with a line break, it's hard
***************
*** 152,182 ****
  and cannot be deleted or replaced.
  
  
! Variable declarations with :let and :const ~
                                                        *vim9-declaration*
! Local variables need to be declared with `:let`.  Local constants need to be
! declared with `:const`.  We refer to both as "variables".
  
  Variables can be local to a script, function or code block: >
        vim9script
!       let script_var = 123
        def SomeFunc()
!         let func_var = script_var
          if cond
!           let block_var = func_var
          ...
  
  The variables are only visible in the block where they are defined and nested
  blocks.  Once the block ends the variable is no longer accessible: >
        if cond
!          let inner = 5
        else
!          let inner = 0
        endif
        echo inner  # Error!
  
  The declaration must be done earlier: >
!       let inner: number
        if cond
           inner = 5
        else
--- 154,185 ----
  and cannot be deleted or replaced.
  
  
! Variable declarations with :var, :final and :const ~
                                                        *vim9-declaration*
! Local variables need to be declared with `:var`.  Local constants need to be
! declared with `:final` or `:const`.  We refer to both as "variables" in this
! section.
  
  Variables can be local to a script, function or code block: >
        vim9script
!       var script_var = 123
        def SomeFunc()
!         var func_var = script_var
          if cond
!           var block_var = func_var
          ...
  
  The variables are only visible in the block where they are defined and nested
  blocks.  Once the block ends the variable is no longer accessible: >
        if cond
!          var inner = 5
        else
!          var inner = 0
        endif
        echo inner  # Error!
  
  The declaration must be done earlier: >
!       var inner: number
        if cond
           inner = 5
        else
***************
*** 184,193 ****
        endif
        echo inner
  
! To intentionally avoid a variable being available later, a block can be used:
! >
        {
!          let temp = 'temp'
           ...
        }
        echo temp  # Error!
--- 187,196 ----
        endif
        echo inner
  
! To intentionally hide a variable from code that follows, a block can be
! used: >
        {
!          var temp = 'temp'
           ...
        }
        echo temp  # Error!
***************
*** 195,203 ****
  Declaring a variable with a type but without an initializer will initialize to
  zero, false or empty.
  
! An existing variable cannot be assigned to with `:let`, since that implies a
! declaration.  Global, window, tab, buffer and Vim variables can only be used
! without `:let`, because they are not really declared, they can also be deleted
  with `:unlet`.
  
  Variables and functions cannot shadow previously defined or imported variables
--- 198,206 ----
  Declaring a variable with a type but without an initializer will initialize to
  zero, false or empty.
  
! In Vim9 script `:let` cannot be used.  An existing variable is assigned to
! without any command.  The same for global, window, tab, buffer and Vim
! variables, because they are not really declared.  They can also be deleted
  with `:unlet`.
  
  Variables and functions cannot shadow previously defined or imported variables
***************
*** 207,257 ****
  Global variables and user defined functions must be prefixed with "g:", also
  at the script level. >
        vim9script
!       let script_local = 'text'
        g:global = 'value'
!       let Funcref = g:ThatFunction
  
! Since "&opt = value" is now assigning a value to option "opt", ":&" cannot be
  used to repeat a `:substitute` command.
-                                                       *vim9-const*
- In legacy Vim script "const list = []" would make the variable "list"
- immutable and also the value.  Thus you cannot add items to the list.  This
- differs from what many languages do. Vim9 script does it like TypeScript: only
- "list" is immutable, the value can be changed.
  
! One can use `:const!` to make both the variable and the value immutable.  Use
  this for composite structures that you want to make sure will not be modified.
  
- How this works: >
-       vim9script
-       const list = [1, 2]
-       list = [3, 4]        # Error!
-       list[0] = 2          # OK
- 
-       const! LIST = [1, 2]
-       LIST = [3, 4]        # Error!
-       LIST[0] = 2          # Error!
  It is common to write constants as ALL_CAPS, but you don't have to.
  
  The constant only applies to the value itself, not what it refers to. >
!       cont females = ["Mary"]
!       const! NAMES = [["John", "Peter"], females]
        NAMES[0] = ["Jack"]     # Error!
!       NAMES[0][0] = ["Jack"]  # Error!
        NAMES[1] = ["Emma"]     # Error!
        Names[1][0] = "Emma"    # OK, now females[0] == "Emma"
  
! Rationale: TypeScript has no way to make the value immutable.  One can use
! immutable types, but that quickly gets complicated for nested values.  And
! with a type cast the value can be made mutable again, which means there is no
! guarantee the value won't change.  Vim supports immutable values, in legacy
! script this was done with `:lockvar`.  But that is an extra statement and also
! applies to nested values.  Therefore the solution to use `:const!`.
! 
!                                                       *E1092*
  Declaring more than one variable at a time, using the unpack notation, is
  currently not supported: >
!       let [v1, v2] = GetValues()  # Error!
  That is because the type needs to be inferred from the list item type, which
  isn't that easy.
  
--- 210,259 ----
  Global variables and user defined functions must be prefixed with "g:", also
  at the script level. >
        vim9script
!       var script_local = 'text'
        g:global = 'value'
!       var Funcref = g:ThatFunction
  
! Since `&opt = value` is now assigning a value to option "opt", ":&" cannot be
  used to repeat a `:substitute` command.
  
! 
! Constants ~
!                                               *vim9-const* *vim9-final*
! How constants work varies between languages.  Some consider a variable that
! can't be assigned another value a constant.  JavaScript is an example.  Others
! also make the value immutable, thus when a constant uses a list, the list
! cannot be changed.  In Vim9 we can use both.
! 
! `:const` is used for making both the variable and the value a constant.  Use
  this for composite structures that you want to make sure will not be modified.
+ Example: >
+       const myList = [1, 2]
+       myList = [3, 4]         # Error!
+       myList[0] = 9           # Error!
+       muList->add(3)          # Error!
+ 
+ `:final` is used for making only the variable a constant, the value can be
+ changed.  This is well known from Java.  Example: >
+       final myList = [1, 2]
+       myList = [3, 4]         # Error!
+       myList[0] = 9           # OK
+       muList->add(3)          # OK
  
  It is common to write constants as ALL_CAPS, but you don't have to.
  
  The constant only applies to the value itself, not what it refers to. >
!       final females = ["Mary"]
!       const NAMES = [["John", "Peter"], females]
        NAMES[0] = ["Jack"]     # Error!
!       NAMES[0][0] = "Jack"    # Error!
        NAMES[1] = ["Emma"]     # Error!
        Names[1][0] = "Emma"    # OK, now females[0] == "Emma"
  
! <                                                     *E1092*
  Declaring more than one variable at a time, using the unpack notation, is
  currently not supported: >
!       var [v1, v2] = GetValues()  # Error!
  That is because the type needs to be inferred from the list item type, which
  isn't that easy.
  
***************
*** 294,300 ****
  without `function()`. The argument types and return type will then be checked.
  The function must already have been defined. >
  
!       let Funcref = MyFunction
  
  When using `function()` the resulting type is "func", a function with any
  number of arguments and any return type.  The function can be defined later.
--- 296,302 ----
  without `function()`. The argument types and return type will then be checked.
  The function must already have been defined. >
  
!       var Funcref = MyFunction
  
  When using `function()` the resulting type is "func", a function with any
  number of arguments and any return type.  The function can be defined later.
***************
*** 305,357 ****
  In many cases it is obvious that an expression continues on the next line.  In
  those cases there is no need to prefix the line with a backslash
  |line-continuation|.  For example, when a list spans multiple lines: >
!       let mylist = [
                'one',
                'two',
                ]
  And when a dict spans multiple lines: >
!       let mydict = #{
                one: 1,
                two: 2,
                }
  Function call: >
!       let result = Func(
                        arg1,
                        arg2
                        )
  
  For binary operators in expressions not in [], {} or () a line break is
  possible just before or after the operator.  For example: >
!       let text = lead
                   .. middle
                   .. end
!       let total = start +
                    end -
                    correction
!       let result = positive
                        ? PosFunc(arg)
                        : NegFunc(arg)
  
  For a method call using "->" and a member using a dot, a line break is allowed
  before it: >
!       let result = GetBuilder()
                        ->BuilderSetWidth(333)
                        ->BuilderSetHeight(777)
                        ->BuilderBuild()
!       let result = MyDict
                        .member
  
  <                                                     *E1050*
  To make it possible for the operator at the start of the line to be
  recognized, it is required to put a colon before a range.  This will add
  "start" and print: >
!       let result = start
        + print
  Like this: >
!       let result = start + print
  
  This will assign "start" and print a line: >
!       let result = start
        :+ print
  
  It is also possible to split a function header over multiple lines, in between
--- 307,359 ----
  In many cases it is obvious that an expression continues on the next line.  In
  those cases there is no need to prefix the line with a backslash
  |line-continuation|.  For example, when a list spans multiple lines: >
!       var mylist = [
                'one',
                'two',
                ]
  And when a dict spans multiple lines: >
!       var mydict = #{
                one: 1,
                two: 2,
                }
  Function call: >
!       var result = Func(
                        arg1,
                        arg2
                        )
  
  For binary operators in expressions not in [], {} or () a line break is
  possible just before or after the operator.  For example: >
!       var text = lead
                   .. middle
                   .. end
!       var total = start +
                    end -
                    correction
!       var result = positive
                        ? PosFunc(arg)
                        : NegFunc(arg)
  
  For a method call using "->" and a member using a dot, a line break is allowed
  before it: >
!       var result = GetBuilder()
                        ->BuilderSetWidth(333)
                        ->BuilderSetHeight(777)
                        ->BuilderBuild()
!       var result = MyDict
                        .member
  
  <                                                     *E1050*
  To make it possible for the operator at the start of the line to be
  recognized, it is required to put a colon before a range.  This will add
  "start" and print: >
!       var result = start
        + print
  Like this: >
!       var result = start + print
  
  This will assign "start" and print a line: >
!       var result = start
        :+ print
  
  It is also possible to split a function header over multiple lines, in between
***************
*** 409,423 ****
  White space ~
  
  Vim9 script enforces proper use of white space.  This is no longer allowed: >
!       let var=234     # Error!
!       let var= 234    # Error!
!       let var =234    # Error!
  There must be white space before and after the "=": >
!       let var = 234   # OK
  White space must also be put before the # that starts a comment after a
  command: >
!       let var = 234# Error!
!       let var = 234 # OK
  
  White space is required around most operators.
  
--- 411,425 ----
  White space ~
  
  Vim9 script enforces proper use of white space.  This is no longer allowed: >
!       var name=234    # Error!
!       var name= 234   # Error!
!       var name =234   # Error!
  There must be white space before and after the "=": >
!       var name = 234  # OK
  White space must also be put before the # that starts a comment after a
  command: >
!       var name = 234# Error!
!       var name = 234 # OK
  
  White space is required around most operators.
  
***************
*** 438,444 ****
  
  Conditions and expressions are mostly working like they do in JavaScript.  A
  difference is made where JavaScript does not work like most people expect.
! Specifically, an empty list is falsey.
  
  Any type of variable can be used as a condition, there is no error, not even
  for using a list or job.  This is very much like JavaScript, but there are a
--- 440,446 ----
  
  Conditions and expressions are mostly working like they do in JavaScript.  A
  difference is made where JavaScript does not work like most people expect.
! Specifically, an empty list is falsy.
  
  Any type of variable can be used as a condition, there is no error, not even
  for using a list or job.  This is very much like JavaScript, but there are a
***************
*** 580,588 ****
                        It is possible to nest `:def` inside another `:def` or
                        `:function` up to about 50 levels deep.
  
!                       [!] is used as with `:function`.  Note that in Vim9
!                       script script-local functions cannot be deleted or
!                       redefined later in the same script.
  
                                                        *:enddef*
  :enddef                       End of a function defined with `:def`. It 
should be on
--- 582,591 ----
                        It is possible to nest `:def` inside another `:def` or
                        `:function` up to about 50 levels deep.
  
!                       [!] is used as with `:function`.  Note that
!                       script-local functions cannot be deleted or redefined
!                       later in Vim9 script.  They can only be removed by
!                       reloading the same script.
  
                                                        *:enddef*
  :enddef                       End of a function defined with `:def`. It 
should be on
***************
*** 610,623 ****
  
  Local variables will not be visible to string evaluation.  For example: >
        def EvalString(): list<string>
!         let list = ['aa', 'bb', 'cc', 'dd']
          return range(1, 2)->map('list[v:val]')
        enddef
  
  The map argument is a string expression, which is evaluated without the
  function scope.  Instead, use a lambda: >
        def EvalString(): list<string>
!         let list = ['aa', 'bb', 'cc', 'dd']
          return range(1, 2)->map({ _, v -> list[v] })
        enddef
  
--- 613,626 ----
  
  Local variables will not be visible to string evaluation.  For example: >
        def EvalString(): list<string>
!         var list = ['aa', 'bb', 'cc', 'dd']
          return range(1, 2)->map('list[v:val]')
        enddef
  
  The map argument is a string expression, which is evaluated without the
  function scope.  Instead, use a lambda: >
        def EvalString(): list<string>
!         var list = ['aa', 'bb', 'cc', 'dd']
          return range(1, 2)->map({ _, v -> list[v] })
        enddef
  
***************
*** 688,710 ****
  
  And classes and interfaces can be used as types: >
        :class MyClass
!       :let mine: MyClass
  
        :interface MyInterface
!       :let mine: MyInterface
  
        :class MyTemplate<Targ>
!       :let mine: MyTemplate<number>
!       :let mine: MyTemplate<string>
  
        :class MyInterface<Targ>
!       :let mine: MyInterface<number>
!       :let mine: MyInterface<string>
  {not implemented yet}
  
  
! Variable types and type casting                               *variable-types*
! 
  Variables declared in Vim9 script or in a `:def` function have a type, either
  specified explicitly or inferred from the initialization.
  
--- 691,713 ----
  
  And classes and interfaces can be used as types: >
        :class MyClass
!       :var mine: MyClass
  
        :interface MyInterface
!       :var mine: MyInterface
  
        :class MyTemplate<Targ>
!       :var mine: MyTemplate<number>
!       :var mine: MyTemplate<string>
  
        :class MyInterface<Targ>
!       :var mine: MyInterface<number>
!       :var mine: MyInterface<string>
  {not implemented yet}
  
  
! Variable types and type casting       ~
!                                                       *variable-types*
  Variables declared in Vim9 script or in a `:def` function have a type, either
  specified explicitly or inferred from the initialization.
  
***************
*** 714,723 ****
  
  This can be a problem when the "any" type is undesired and the actual type is
  expected to always be the same.  For example, when declaring a list: >
!       let l: list<number> = [1, g:two]
  This will give an error, because "g:two" has type "any".  To avoid this, use a
  type cast: >
!       let l: list<number> = [1, <number>g:two]
  <                                                     *type-casting*
  The compiled code will then check that "g:two" is a number at runtime and give
  an error if it isn't.  This is called type casting.
--- 717,726 ----
  
  This can be a problem when the "any" type is undesired and the actual type is
  expected to always be the same.  For example, when declaring a list: >
!       var l: list<number> = [1, g:two]
  This will give an error, because "g:two" has type "any".  To avoid this, use a
  type cast: >
!       var l: list<number> = [1, <number>g:two]
  <                                                     *type-casting*
  The compiled code will then check that "g:two" is a number at runtime and give
  an error if it isn't.  This is called type casting.
***************
*** 732,743 ****
  string to a number.
  
  
! Type inference                                                *type-inference*
! 
  In general: Whenever the type is clear it can be omitted.  For example, when
  declaring a variable and giving it a value: >
!       let var = 0             # infers number type
!       let var = 'hello'       # infers string type
  
  The type of a list and dictionary comes from the common type of the values.
  If the values all have the same type, that type is used for the list or
--- 735,746 ----
  string to a number.
  
  
! Type inference ~
!                                                       *type-inference*
  In general: Whenever the type is clear it can be omitted.  For example, when
  declaring a variable and giving it a value: >
!       var name = 0            # infers number type
!       var name = 'hello'      # infers string type
  
  The type of a list and dictionary comes from the common type of the values.
  If the values all have the same type, that type is used for the list or
***************
*** 747,754 ****
        [1, 'x', 3]     list<any>
  
  
! Stricter type checking                                        *type-checking*
! 
  In legacy Vim script, where a number was expected, a string would be
  automatically converted to a number.  This was convenient for an actual number
  such as "123", but leads to unexpected problems (but no error message) if the
--- 750,757 ----
        [1, 'x', 3]     list<any>
  
  
! Stricter type checking ~
!                                                       *type-checking*
  In legacy Vim script, where a number was expected, a string would be
  automatically converted to a number.  This was convenient for an actual number
  such as "123", but leads to unexpected problems (but no error message) if the
***************
*** 764,770 ****
  
  ==============================================================================
  
! 5.  Namespace, Import and Export
                                        *vim9script* *vim9-export* *vim9-import*
  
  THIS IS STILL UNDER DEVELOPMENT - ANYTHING CAN BREAK - ANYTHING CAN CHANGE
--- 767,773 ----
  
  ==============================================================================
  
! 5. Namespace, Import and Export
                                        *vim9script* *vim9-export* *vim9-import*
  
  THIS IS STILL UNDER DEVELOPMENT - ANYTHING CAN BREAK - ANYTHING CAN CHANGE
***************
*** 784,790 ****
  script in its own namespace, instead of the global namespace.  If a file
  starts with: >
        vim9script
!       let myvar = 'yes'
  Then "myvar" will only exist in this file.  While without `vim9script` it 
would
  be available as `g:myvar` from any other script and function.
  
--- 787,793 ----
  script in its own namespace, instead of the global namespace.  If a file
  starts with: >
        vim9script
!       var myvar = 'yes'
  Then "myvar" will only exist in this file.  While without `vim9script` it 
would
  be available as `g:myvar` from any other script and function.
  
***************
*** 807,813 ****
                                                        *:export* *:exp*
  Exporting an item can be written as: >
        export const EXPORTED_CONST = 1234
!       export let someValue = ...
        export def MyFunc() ...
        export class MyClass ...
  
--- 810,818 ----
                                                        *:export* *:exp*
  Exporting an item can be written as: >
        export const EXPORTED_CONST = 1234
!       export var someValue = ...
!       export final someValue = ...
!       export const someValue = ...
        export def MyFunc() ...
        export class MyClass ...
  
***************
*** 834,839 ****
--- 839,846 ----
  To import all exported items under a specific identifier: >
        import * as That from 'thatscript.vim'
  
+ {not implemented yet: using "This as That"}
+ 
  Then you can use "That.EXPORTED_CONST", "That.someValue", etc.  You are free
  to choose the name "That", but it is highly recommended to use the name of the
  script file to avoid confusion.
***************
*** 876,882 ****
        vim9script
          import FilterFunc from "../import/someother.vim"
        def searchfor#Stuff(arg: string)
!         let filtered = FilterFunc(arg)
          ...
  <   This goes in .../autoload/searchfor.vim.  "searchfor" in the file name
     must be exactly the same as the prefix for the function name, that is how
--- 883,889 ----
        vim9script
          import FilterFunc from "../import/someother.vim"
        def searchfor#Stuff(arg: string)
!         var filtered = FilterFunc(arg)
          ...
  <   This goes in .../autoload/searchfor.vim.  "searchfor" in the file name
     must be exactly the same as the prefix for the function name, that is how
***************
*** 885,891 ****
  3. Other functionality, possibly shared between plugins, contains the exported
     items and any private items. >
        vim9script
!       let localVar = 'local'
        export def FilterFunc(arg: string): string
           ...
  <   This goes in .../import/someother.vim.
--- 892,898 ----
  3. Other functionality, possibly shared between plugins, contains the exported
     items and any private items. >
        vim9script
!       var localVar = 'local'
        export def FilterFunc(arg: string): string
           ...
  <   This goes in .../import/someother.vim.
***************
*** 902,912 ****
  
  ==============================================================================
  
  9. Rationale                                          *vim9-rationale*
  
  The :def command ~
  
! Plugin writers have asked for a much faster Vim script.  Investigations have
  shown that keeping the existing semantics of function calls make this close to
  impossible, because of the overhead involved with calling a function, setting
  up the local function scope and executing lines.  There are many details that
--- 909,950 ----
  
  ==============================================================================
  
+ 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`, everything in one file
+ - Class names are always CamelCase
+ - Single constructor
+ - Single inheritance with `class ThisClass extends BaseClass`
+ - `abstract class`
+ - `interface` (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.
+ 
+ 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)
+ 
+ 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.
+ 
+ ==============================================================================
+ 
  9. Rationale                                          *vim9-rationale*
  
  The :def command ~
  
! Plugin writers have asked for much faster Vim script.  Investigations have
  shown that keeping the existing semantics of function calls make this close to
  impossible, because of the overhead involved with calling a function, setting
  up the local function scope and executing lines.  There are many details that
***************
*** 917,923 ****
  Therefore the `:def` method to define a new-style function had to be added,
  which allows for a function with different semantics.  Most things still work
  as before, but some parts do not.  A new way to define a function was
! considered the best way to separate the old-style code from Vim9 script code.
  
  Using "def" to define a function comes from Python. Other languages use
  "function" which clashes with legacy Vim script.
--- 955,961 ----
  Therefore the `:def` method to define a new-style function had to be added,
  which allows for a function with different semantics.  Most things still work
  as before, but some parts do not.  A new way to define a function was
! considered the best way to separate the legacy style code from Vim9 style 
code.
  
  Using "def" to define a function comes from Python. Other languages use
  "function" which clashes with legacy Vim script.
***************
*** 933,1007 ****
  of the arguments and decide what kind of addition to do.  And when the
  type is dictionary throw an error.  If the types are known to be numbers then
  an "add number" instruction can be used, which is faster.  The error can be
! given at compile time, no error handling is needed at runtime.
  
! The syntax for types is similar to Java, since it is easy to understand and
! widely used.  The type names are what were used in Vim before, with some
! additions such as "void" and "bool".
  
  
! Compiling functions early ~
  
! Functions are compiled when called or when `:defcompile` is used.  Why not
! compile them early, so that syntax and type errors are reported early?
  
! The functions can't be compiled right away when encountered, because there may
! be forward references to functions defined later.  Consider defining functions
! A, B and C, where A calls B, B calls C, and C calls A again.  It's impossible
! to reorder the functions to avoid forward references.
  
! An alternative would be to first scan through the file to locate items and
! figure out their type, so that forward references are found, and only then
! execute the script and compile the functions.  This means the script has to be
! parsed twice, which is slower, and some conditions at the script level, such
! as checking if a feature is supported, are hard to use.  An attempt was made
! to see if it works, but it turned out to be impossible to make work nicely.
  
! It would be possible to compile all the functions at the end of the script.
! The drawback is that if a function never gets called, the overhead of
! compiling it counts anyway.  Since startup speed is very important, in most
! cases it's better to do it later and accept that syntax and type errors are
! only reported then.  In case these errors should be found early, e.g. when
! testing, the `:defcompile` command will help out.
  
  
! TypeScript syntax and semantics ~
  
  Script writers have complained that the Vim script syntax is unexpectedly
  different from what they are used to.  To reduce this complaint popular
  languages are used as an example.  At the same time, we do not want to abandon
  the well-known parts of legacy Vim script.
  
! Since Vim already uses `:let` and `:const` and optional type checking is
! desirable, the JavaScript/TypeScript syntax fits best for variable
! declarations: >
!       const greeting = 'hello'  # string type is inferred
!       let name: string
!       ...
!       name = 'John'
! 
! Expression evaluation was already close to what JavaScript and other languages
! are doing.  Some details are unexpected and can be fixed.  For example how the
! || and && operators work.  Legacy Vim script: >
!       let value = 44
!       ...
!       let result = value || 0  # result == 1
! 
! Vim9 script works like JavaScript/TypeScript, keep the value: >
!       let value = 44
!       ...
!       let result = value || 0  # result == 44
  
  There is no intention to completely match TypeScript syntax and semantics.  We
  just want to take those parts that we can use for Vim and we expect Vim users
! will be happy with.  TypeScript is a complex language with its own advantages
! and disadvantages.  To get an idea of the disadvantages read the book:
! "JavaScript: The Good Parts".  Or find the article "TypeScript: the good
  parts" and read the "Things to avoid" section.
  
! People used to other languages (Java, Python, etc.) will also find things in
! TypeScript that they do not like or do not understand.  We'll try to avoid
! those things.
  
  Specific items from TypeScript we avoid:
  - Overloading "+", using it both for addition and string concatenation.  This
--- 971,1035 ----
  of the arguments and decide what kind of addition to do.  And when the
  type is dictionary throw an error.  If the types are known to be numbers then
  an "add number" instruction can be used, which is faster.  The error can be
! given at compile time, no error handling is needed at runtime, since adding
! two numbers cannot fail.
  
! The syntax for types, using <type> for compound types, is similar to Java.  It
! is easy to understand and widely used.  The type names are what were used in
! Vim before, with some additions such as "void" and "bool".
  
  
! Removing clutter and weirdness ~
  
! Once decided that `:def` functions have different syntax than legacy 
functions,
! we are free to add improvements to make the code more familiar for users who
! know popular programming languages.  In other words: remove weird things that
! only Vim does.
  
! We can also remove clutter, mainly things that were done to make Vim script
! backwards compatible with the good old Vi commands.
  
! Examples:
! - Drop `:call` for calling a function and `:eval` for manipulating data.
! - Drop using a leading backslash for line continuation, automatically figure
!   out where an expression ends.
  
! However, this does require that some things need to change:
! - Comments start with # instead of ", to avoid confusing them with strings.
!   This is good anyway, it is known from several popular languages.
! - Ex command ranges need to be prefixed with a colon, to avoid confusion with
!   expressions (single quote can be a string or a mark, "/" can be divide or a
!   search command, etc.).
! 
! Goal is to limit the differences.  A good criteria is that when the old syntax
! is accidentally used you are very likely to get an error message.
  
  
! Syntax and semantics from popular languages ~
  
  Script writers have complained that the Vim script syntax is unexpectedly
  different from what they are used to.  To reduce this complaint popular
  languages are used as an example.  At the same time, we do not want to abandon
  the well-known parts of legacy Vim script.
  
! For many things TypeScript is followed.  It's a recent language that is
! gaining popularity and has similarities with Vim script.  It also has a
! mix of static typing (a variable always has a known value type) and dynamic
! typing (a variable can have different types, this changes at runtime).  Since
! legacy Vim script is dynamically typed and a lot of existing functionality
! (esp. builtin functions) depends on that, while static typing allows for much
! faster execution, we need to have this mix in Vim9 script.
  
  There is no intention to completely match TypeScript syntax and semantics.  We
  just want to take those parts that we can use for Vim and we expect Vim users
! will be happy with.  TypeScript is a complex language with its own history,
! advantages and disadvantages.  To get an idea of the disadvantages read the
! book: "JavaScript: The Good Parts".  Or find the article "TypeScript: the good
  parts" and read the "Things to avoid" section.
  
! People familiar with other languages (Java, Python, etc.) will also find
! things in TypeScript that they do not like or do not understand.  We'll try to
! avoid those things.
  
  Specific items from TypeScript we avoid:
  - Overloading "+", using it both for addition and string concatenation.  This
***************
*** 1011,1017 ****
  - TypeScript can use an expression like "99 || 'yes'" in a condition, but
    cannot assign the value to a boolean.  That is inconsistent and can be
    annoying.  Vim recognizes an expression with && or || and allows using the
!   result as a bool.
  - TypeScript considers an empty string as Falsy, but an empty list or dict as
    Truthy.  That is inconsistent.  In Vim an empty list and dict are also
    Falsy.
--- 1039,1045 ----
  - TypeScript can use an expression like "99 || 'yes'" in a condition, but
    cannot assign the value to a boolean.  That is inconsistent and can be
    annoying.  Vim recognizes an expression with && or || and allows using the
!   result as a bool.  TODO: to be reconsidered
  - TypeScript considers an empty string as Falsy, but an empty list or dict as
    Truthy.  That is inconsistent.  In Vim an empty list and dict are also
    Falsy.
***************
*** 1020,1025 ****
--- 1048,1127 ----
    which is more flexible, but is only checked at runtime.
  
  
+ Declarations ~
+ 
+ Legacy Vim script uses `:let` for every assignment, while in Vim9 declarations
+ are used.  That is different, thus it's good to use a different command:
+ `:var`.  This is used in many languages.  The semantics might be slightly
+ different, but it's easily recognized as a declaration.
+ 
+ Using `:const`  for constants is common, but the semantics vary.  Some
+ languages only make the variable immutable, others also make the value
+ immutable.  Since "final" is well known from Java for only making the variable
+ immutable we decided to use that.  And then `:const` can be used for making
+ both immutable.  This was also used in legacy Vim script and the meaning is
+ almost the same.
+ 
+ What we end up with is very similar to Dart: >
+       :var name       # mutable variable and value
+       :final name     # immutable variable, mutable value
+       :const name     # immutable variable and value
+ 
+ Since legacy and Vim9 script will be mixed and global variables will be
+ shared, optional type checking is desirable.  Also, type inference will avoid
+ the need for specifying the type in many cases.  The TypeScript syntax fits
+ best for adding types to declarations: >
+       var name: string          # string type is specified
+       ...
+       name = 'John'
+       const greeting = 'hello'  # string type is inferred
+ 
+ This is how we put types in a declaration: >
+       var mylist: list<string>
+       final mylist: list<string> = ['foo']
+       def Func(arg1: number, arg2: string): bool
+ 
+ Two alternatives were considered:
+ 1. Put the type before the name, like Dart: >
+       var list<string> mylist
+       final list<string> mylist = ['foo']
+       def Func(number arg1, string arg2) bool
+ 2. Put the type after the variable name, but do not use a colon, like Go: >
+       var mylist list<string>
+       final mylist list<string> = ['foo']
+       def Func(arg1 number, arg2 string) bool
+ 
+ The first is more familiar for anyone used to C or Java.  The second one
+ doesn't really has an advantage over the first, so let's discard the second.
+ 
+ Since we use type inference the type can be left out when it can be inferred
+ from the value.  This means that after `var` we don't know if a type or a name
+ follows.  That makes parsing harder, not only for Vim but also for humans.
+ Also, it will not be allowed to use a variable name that could be a type name,
+ using `var string string` is too confusing.
+ 
+ The chosen syntax, using a colon to separate the name from the type, adds
+ punctuation, but it actually makes it easier to recognize the parts of a
+ declaration.
+ 
+ 
+ Expressions ~
+ 
+ Expression evaluation was already close to what JavaScript and other languages
+ are doing.  Some details are unexpected and can be fixed.  For example how the
+ || and && operators work.  Legacy Vim script: >
+       var value = 44
+       ...
+       var result = value || 0  # result == 1
+ 
+ Vim9 script works like JavaScript/TypeScript, keep the value: >
+       var value = 44
+       ...
+       var result = value || 0  # result == 44
+ 
+ TODO: the semantics of || and && need to be reconsidered.
+ 
+ 
  Import and Export ~
  
  A problem of legacy Vim script is that by default all functions and variables
***************
*** 1054,1077 ****
  Note that you can also use `:import` in legacy Vim script, see above.
  
  
! Classes ~
  
  Vim supports interfaces to Perl, Python, Lua, Tcl and a few others.  But
! these interfaces have never become widespread.  When Vim 9 was designed a
! decision was made to phase out these interfaces and concentrate on Vim script,
! while encouraging plugin authors to write code in any language and run it as
! an external tool, using jobs and channels.
  
! Still, using an external tool has disadvantages.  An alternative is to convert
  the tool into Vim script.  For that to be possible without too much
  translation, and keeping the code fast at the same time, the constructs of the
  tool need to be supported.  Since most languages support classes the lack of
  support for classes in Vim is then a problem.
  
! Previously Vim supported a kind-of object oriented programming by adding
! methods to a dictionary.  With some care this could be made to work, but it
! does not look like real classes.  On top of that, it's very slow, because of
! the use of dictionaries.
  
  The support of classes in Vim9 script is a "minimal common functionality" of
  class support in most languages.  It works much like Java, which is the most
--- 1156,1211 ----
  Note that you can also use `:import` in legacy Vim script, see above.
  
  
! Compiling functions early ~
! 
! Functions are compiled when called or when `:defcompile` is used.  Why not
! compile them early, so that syntax and type errors are reported early?
! 
! The functions can't be compiled right away when encountered, because there may
! be forward references to functions defined later.  Consider defining functions
! A, B and C, where A calls B, B calls C, and C calls A again.  It's impossible
! to reorder the functions to avoid forward references.
! 
! An alternative would be to first scan through the file to locate items and
! figure out their type, so that forward references are found, and only then
! execute the script and compile the functions.  This means the script has to be
! parsed twice, which is slower, and some conditions at the script level, such
! as checking if a feature is supported, are hard to use.  An attempt was made
! to see if it works, but it turned out to be impossible to make work nicely.
! 
! It would be possible to compile all the functions at the end of the script.
! The drawback is that if a function never gets called, the overhead of
! compiling it counts anyway.  Since startup speed is very important, in most
! cases it's better to do it later and accept that syntax and type errors are
! only reported then.  In case these errors should be found early, e.g. when
! testing, the `:defcompile` command will help out.
! 
! 
! Why not use an embedded language? ~
  
  Vim supports interfaces to Perl, Python, Lua, Tcl and a few others.  But
! these interfaces have never become widely used, for various reasons.  When
! Vim9 was designed a decision was made to make these interfaces lower priority
! and concentrate on Vim script.
! 
! Still, plugin writers may find other languages more familiar, want to use
! existing libraries or see a performance benefit.  We encourage plugin authors
! to write code in any language and run it as an external tool, using jobs and
! channels.  We can try to make this easier somehow.
  
! Using an external tool also has disadvantages.  An alternative is to convert
  the tool into Vim script.  For that to be possible without too much
  translation, and keeping the code fast at the same time, the constructs of the
  tool need to be supported.  Since most languages support classes the lack of
  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.
  
  The support of classes in Vim9 script is a "minimal common functionality" of
  class support in most languages.  It works much like Java, which is the most
*** ../vim-8.2.1743/src/ex_cmds.h       2020-09-14 21:38:47.752976295 +0200
--- src/ex_cmds.h       2020-09-26 12:24:50.169245524 +0200
***************
*** 592,597 ****
--- 592,600 ----
  EXCMD(CMD_find,               "find",         ex_find,
        EX_RANGE|EX_BANG|EX_FILE1|EX_CMDARG|EX_ARGOPT|EX_TRLBAR|EX_NEEDARG,
        ADDR_OTHER),
+ EXCMD(CMD_final,      "final",        ex_let,
+       EX_EXTRA|EX_NOTRLCOM|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK,
+       ADDR_NONE),
  EXCMD(CMD_finally,    "finally",      ex_finally,
        EX_TRLBAR|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK,
        ADDR_NONE),
***************
*** 1648,1653 ****
--- 1651,1659 ----
  EXCMD(CMD_vglobal,    "vglobal",      ex_global,
        EX_RANGE|EX_WHOLEFOLD|EX_EXTRA|EX_DFLALL|EX_CMDWIN|EX_LOCK_OK,
        ADDR_LINES),
+ EXCMD(CMD_var,                "var",          ex_var,
+       EX_EXTRA|EX_NOTRLCOM|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK,
+       ADDR_NONE),
  EXCMD(CMD_version,    "version",      ex_version,
        EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
        ADDR_NONE),
*** ../vim-8.2.1743/src/errors.h        2020-09-20 22:43:48.205496879 +0200
--- src/errors.h        2020-09-26 14:02:19.636724346 +0200
***************
*** 270,273 ****
--- 270,277 ----
        INIT(= N_("E1122: Variable is locked: %s"));
  EXTERN char e_missing_comma_before_argument_str[]
        INIT(= N_("E1123: Missing comma before argument: %s"));
+ EXTERN char e_str_cannot_be_used_in_legacy_vim_script[]
+       INIT(= N_("E1124: \"%s\" cannot be used in legacy Vim script"));
+ EXTERN char e_final_requires_a_value[]
+       INIT(= N_("E1125: Final requires a value"));
  #endif
*** ../vim-8.2.1743/src/evalvars.c      2020-09-16 21:08:23.642361197 +0200
--- src/evalvars.c      2020-09-26 12:25:21.189152367 +0200
***************
*** 669,674 ****
--- 669,693 ----
  }
  
  /*
+  * Vim9 variable declaration:
+  * ":var name"
+  * ":var name: type"
+  * ":var name = expr"
+  * ":var name: type = expr"
+  * etc.
+  */
+     void
+ ex_var(exarg_T *eap)
+ {
+     if (!in_vim9script())
+     {
+       semsg(_(e_str_cannot_be_used_in_legacy_vim_script), ":var");
+       return;
+     }
+     ex_let(eap);
+ }
+ 
+ /*
   * ":let"                     list all variable values
   * ":let var1 var2"           list variable values
   * ":let var = expr"          assignment command.
***************
*** 683,688 ****
--- 702,710 ----
   * ":let var =<< ..."         heredoc
   * ":let var: string"         Vim9 declaration
   *
+  * ":final var = expr"                assignment command.
+  * ":final [var1, var2] = expr"       unpack list.
+  *
   * ":const"                   list all variable values
   * ":const var1 var2"         list variable values
   * ":const var = expr"                assignment command.
***************
*** 702,715 ****
      int               first = TRUE;
      int               concat;
      int               has_assign;
!     int               flags = eap->cmdidx == CMD_const ? LET_IS_CONST : 0;
      int               vim9script = in_vim9script();
  
      // detect Vim9 assignment without ":let" or ":const"
      if (eap->arg == eap->cmd)
!       flags |= LET_NO_COMMAND;
!     if (eap->forceit)
!       flags |= LET_FORCEIT;
  
      argend = skip_var_list(arg, TRUE, &var_count, &semicolon, FALSE);
      if (argend == NULL)
--- 724,745 ----
      int               first = TRUE;
      int               concat;
      int               has_assign;
!     int               flags = eap->cmdidx == CMD_const ? ASSIGN_CONST : 0;
      int               vim9script = in_vim9script();
  
+     if (eap->cmdidx == CMD_final && !vim9script)
+     {
+           // In legacy Vim script ":final" is short for ":finally".
+           ex_finally(eap);
+           return;
+     }
+     if (eap->cmdidx == CMD_const && !vim9script && !eap->forceit)
+       // In legacy Vim script ":const" works like ":final".
+       eap->cmdidx = CMD_final;
+ 
      // detect Vim9 assignment without ":let" or ":const"
      if (eap->arg == eap->cmd)
!       flags |= ASSIGN_NO_DECL;
  
      argend = skip_var_list(arg, TRUE, &var_count, &semicolon, FALSE);
      if (argend == NULL)
***************
*** 787,793 ****
            op[1] = NUL;
            if (*expr != '=')
            {
!               if (vim9script && (flags & LET_NO_COMMAND) == 0)
                {
                    // +=, /=, etc. require an existing variable
                    semsg(_(e_cannot_use_operator_on_new_variable), eap->arg);
--- 817,823 ----
            op[1] = NUL;
            if (*expr != '=')
            {
!               if (vim9script && (flags & ASSIGN_NO_DECL) == 0)
                {
                    // +=, /=, etc. require an existing variable
                    semsg(_(e_cannot_use_operator_on_new_variable), eap->arg);
***************
*** 860,866 ****
      int               copy,           // copy values from "tv", don't move
      int               semicolon,      // from skip_var_list()
      int               var_count,      // from skip_var_list()
!     int               flags,          // LET_IS_CONST, LET_FORCEIT, 
LET_NO_COMMAND
      char_u    *op)
  {
      char_u    *arg = arg_start;
--- 890,896 ----
      int               copy,           // copy values from "tv", don't move
      int               semicolon,      // from skip_var_list()
      int               var_count,      // from skip_var_list()
!     int               flags,          // ASSIGN_CONST, ASSIGN_NO_DECL
      char_u    *op)
  {
      char_u    *arg = arg_start;
***************
*** 1215,1221 ****
      char_u    *arg,           // points to variable name
      typval_T  *tv,            // value to assign to variable
      int               copy,           // copy value from "tv"
!     int               flags,          // LET_IS_CONST, LET_FORCEIT, 
LET_NO_COMMAND
      char_u    *endchars,      // valid chars after variable name  or NULL
      char_u    *op)            // "+", "-", "."  or NULL
  {
--- 1245,1251 ----
      char_u    *arg,           // points to variable name
      typval_T  *tv,            // value to assign to variable
      int               copy,           // copy value from "tv"
!     int               flags,          // ASSIGN_CONST, ASSIGN_NO_DECL
      char_u    *endchars,      // valid chars after variable name  or NULL
      char_u    *op)            // "+", "-", "."  or NULL
  {
***************
*** 1227,1233 ****
      int               opt_flags;
      char_u    *tofree = NULL;
  
!     if (in_vim9script() && (flags & LET_NO_COMMAND) == 0
                                  && vim_strchr((char_u *)"$@&", *arg) != NULL)
      {
        vim9_declare_error(arg);
--- 1257,1263 ----
      int               opt_flags;
      char_u    *tofree = NULL;
  
!     if (in_vim9script() && (flags & ASSIGN_NO_DECL) == 0
                                  && vim_strchr((char_u *)"$@&", *arg) != NULL)
      {
        vim9_declare_error(arg);
***************
*** 1237,1243 ****
      // ":let $VAR = expr": Set environment variable.
      if (*arg == '$')
      {
!       if (flags & LET_IS_CONST)
        {
            emsg(_("E996: Cannot lock an environment variable"));
            return NULL;
--- 1267,1273 ----
      // ":let $VAR = expr": Set environment variable.
      if (*arg == '$')
      {
!       if (flags & ASSIGN_CONST)
        {
            emsg(_("E996: Cannot lock an environment variable"));
            return NULL;
***************
*** 1289,1295 ****
      // ":let &g:option = expr": Set global option value.
      else if (*arg == '&')
      {
!       if (flags & LET_IS_CONST)
        {
            emsg(_(e_const_option));
            return NULL;
--- 1319,1325 ----
      // ":let &g:option = expr": Set global option value.
      else if (*arg == '&')
      {
!       if (flags & ASSIGN_CONST)
        {
            emsg(_(e_const_option));
            return NULL;
***************
*** 1373,1379 ****
      // ":let @r = expr": Set register contents.
      else if (*arg == '@')
      {
!       if (flags & LET_IS_CONST)
        {
            emsg(_("E996: Cannot lock a register"));
            return NULL;
--- 1403,1409 ----
      // ":let @r = expr": Set register contents.
      else if (*arg == '@')
      {
!       if (flags & ASSIGN_CONST)
        {
            emsg(_("E996: Cannot lock a register"));
            return NULL;
***************
*** 2926,2932 ****
      typval_T  *tv,
      int               copy)       // make copy of value in "tv"
  {
!     set_var_const(name, NULL, tv, copy, LET_NO_COMMAND);
  }
  
  /*
--- 2956,2962 ----
      typval_T  *tv,
      int               copy)       // make copy of value in "tv"
  {
!     set_var_const(name, NULL, tv, copy, ASSIGN_NO_DECL);
  }
  
  /*
***************
*** 2940,2946 ****
      type_T    *type,
      typval_T  *tv_arg,
      int               copy,       // make copy of value in "tv"
!     int               flags)      // LET_IS_CONST, LET_FORCEIT, LET_NO_COMMAND
  {
      typval_T  *tv = tv_arg;
      typval_T  bool_tv;
--- 2970,2976 ----
      type_T    *type,
      typval_T  *tv_arg,
      int               copy,       // make copy of value in "tv"
!     int               flags)      // ASSIGN_CONST, ASSIGN_NO_DECL
  {
      typval_T  *tv = tv_arg;
      typval_T  bool_tv;
***************
*** 2960,2966 ****
  
      if (vim9script
            && !is_script_local
!           && (flags & LET_NO_COMMAND) == 0
            && name[1] == ':')
      {
        vim9_declare_error(name);
--- 2990,2996 ----
  
      if (vim9script
            && !is_script_local
!           && (flags & ASSIGN_NO_DECL) == 0
            && name[1] == ':')
      {
        vim9_declare_error(name);
***************
*** 2990,2996 ****
      {
        if ((di->di_flags & DI_FLAGS_RELOAD) == 0)
        {
!           if (flags & LET_IS_CONST)
            {
                emsg(_(e_cannot_mod));
                goto failed;
--- 3020,3026 ----
      {
        if ((di->di_flags & DI_FLAGS_RELOAD) == 0)
        {
!           if (flags & ASSIGN_CONST)
            {
                emsg(_(e_cannot_mod));
                goto failed;
***************
*** 2998,3004 ****
  
            if (is_script_local && vim9script)
            {
!               if ((flags & LET_NO_COMMAND) == 0)
                {
                    semsg(_(e_redefining_script_item_str), name);
                    goto failed;
--- 3028,3034 ----
  
            if (is_script_local && vim9script)
            {
!               if ((flags & ASSIGN_NO_DECL) == 0)
                {
                    semsg(_(e_redefining_script_item_str), name);
                    goto failed;
***************
*** 3094,3100 ****
            goto failed;
        }
        di->di_flags = DI_FLAGS_ALLOC;
!       if (flags & LET_IS_CONST)
            di->di_flags |= DI_FLAGS_LOCK;
  
        if (is_script_local && vim9script)
--- 3124,3130 ----
            goto failed;
        }
        di->di_flags = DI_FLAGS_ALLOC;
!       if (flags & ASSIGN_CONST)
            di->di_flags |= DI_FLAGS_LOCK;
  
        if (is_script_local && vim9script)
***************
*** 3113,3119 ****
                    sv->sv_type = typval2type(tv, &si->sn_type_list);
                else
                    sv->sv_type = type;
!               sv->sv_const = (flags & LET_IS_CONST);
                sv->sv_export = is_export;
                ++si->sn_var_vals.ga_len;
  
--- 3143,3149 ----
                    sv->sv_type = typval2type(tv, &si->sn_type_list);
                else
                    sv->sv_type = type;
!               sv->sv_const = (flags & ASSIGN_CONST);
                sv->sv_export = is_export;
                ++si->sn_var_vals.ga_len;
  
***************
*** 3132,3139 ****
        init_tv(tv);
      }
  
!     // ":const var = val" locks the value; in Vim9 script only with ":const!"
!     if ((flags & LET_IS_CONST) && (!vim9script || (flags & LET_FORCEIT)))
        // Like :lockvar! name: lock the value and what it contains, but only
        // if the reference count is up to one.  That locks only literal
        // values.
--- 3162,3169 ----
        init_tv(tv);
      }
  
!     // ":const var = val" locks the value
!     if (flags & ASSIGN_CONST)
        // Like :lockvar! name: lock the value and what it contains, but only
        // if the reference count is up to one.  That locks only literal
        // values.
*** ../vim-8.2.1743/src/proto/evalvars.pro      2020-09-16 21:08:23.642361197 
+0200
--- src/proto/evalvars.pro      2020-09-26 12:25:47.813072395 +0200
***************
*** 14,19 ****
--- 14,20 ----
  void prepare_vimvar(int idx, typval_T *save_tv);
  void restore_vimvar(int idx, typval_T *save_tv);
  list_T *heredoc_get(exarg_T *eap, char_u *cmd, int script_get);
+ void ex_var(exarg_T *eap);
  void ex_let(exarg_T *eap);
  int ex_let_vars(char_u *arg_start, typval_T *tv, int copy, int semicolon, int 
var_count, int flags, char_u *op);
  char_u *skip_var_list(char_u *arg, int include_type, int *var_count, int 
*semicolon, int silent);
*** ../vim-8.2.1743/src/cmdexpand.c     2020-09-14 16:37:30.906845912 +0200
--- src/cmdexpand.c     2020-09-26 11:58:07.489987920 +0200
***************
*** 1513,1520 ****
--- 1513,1522 ----
            break;
  #endif
  #ifdef FEAT_EVAL
+       case CMD_final:
        case CMD_const:
        case CMD_let:
+       case CMD_var:
        case CMD_if:
        case CMD_elseif:
        case CMD_while:
*** ../vim-8.2.1743/src/eval.c  2020-09-23 15:56:47.132579290 +0200
--- src/eval.c  2020-09-26 12:24:37.213284437 +0200
***************
*** 1213,1219 ****
      char_u    *endp,
      typval_T  *rettv,
      int               copy,
!     int               flags,    // LET_IS_CONST, LET_FORCEIT, LET_NO_COMMAND
      char_u    *op)
  {
      int               cc;
--- 1213,1219 ----
      char_u    *endp,
      typval_T  *rettv,
      int               copy,
!     int               flags,    // ASSIGN_CONST, ASSIGN_NO_DECL
      char_u    *op)
  {
      int               cc;
***************
*** 1281,1287 ****
        {
            typval_T tv;
  
!           if (flags & LET_IS_CONST)
            {
                emsg(_(e_cannot_mod));
                *endp = cc;
--- 1281,1287 ----
        {
            typval_T tv;
  
!           if (flags & ASSIGN_CONST)
            {
                emsg(_(e_cannot_mod));
                *endp = cc;
***************
*** 1319,1325 ****
        listitem_T *ll_li = lp->ll_li;
        int         ll_n1 = lp->ll_n1;
  
!       if (flags & LET_IS_CONST)
        {
            emsg(_("E996: Cannot lock a range"));
            return;
--- 1319,1325 ----
        listitem_T *ll_li = lp->ll_li;
        int         ll_n1 = lp->ll_n1;
  
!       if (flags & ASSIGN_CONST)
        {
            emsg(_("E996: Cannot lock a range"));
            return;
***************
*** 1378,1384 ****
        /*
         * Assign to a List or Dictionary item.
         */
!       if (flags & LET_IS_CONST)
        {
            emsg(_("E996: Cannot lock a list or dict"));
            return;
--- 1378,1384 ----
        /*
         * Assign to a List or Dictionary item.
         */
!       if (flags & ASSIGN_CONST)
        {
            emsg(_("E996: Cannot lock a list or dict"));
            return;
***************
*** 1688,1694 ****
  {
      forinfo_T *fi = (forinfo_T *)fi_void;
      int               result;
!     int               flag = in_vim9script() ?  LET_NO_COMMAND : 0;
      listitem_T        *item;
  
      if (fi->fi_blob != NULL)
--- 1688,1694 ----
  {
      forinfo_T *fi = (forinfo_T *)fi_void;
      int               result;
!     int               flag = in_vim9script() ?  ASSIGN_NO_DECL : 0;
      listitem_T        *item;
  
      if (fi->fi_blob != NULL)
***************
*** 1741,1751 ****
      char_u    *arg,
      cmdidx_T  cmdidx)
  {
!     int               got_eq = FALSE;
      int               c;
      char_u    *p;
  
!     if (cmdidx == CMD_let || cmdidx == CMD_const)
      {
        xp->xp_context = EXPAND_USER_VARS;
        if (vim_strpbrk(arg, (char_u *)"\"'+-*/%.=!?~|&$([<>,#") == NULL)
--- 1741,1752 ----
      char_u    *arg,
      cmdidx_T  cmdidx)
  {
!     int               has_expr = cmdidx != CMD_let && cmdidx != CMD_var;
      int               c;
      char_u    *p;
  
!     if (cmdidx == CMD_let || cmdidx == CMD_var
!                                || cmdidx == CMD_const || cmdidx == CMD_final)
      {
        xp->xp_context = EXPAND_USER_VARS;
        if (vim_strpbrk(arg, (char_u *)"\"'+-*/%.=!?~|&$([<>,#") == NULL)
***************
*** 1774,1781 ****
            if (c == '&')
            {
                ++xp->xp_pattern;
!               xp->xp_context = cmdidx != CMD_let || got_eq
!                                        ? EXPAND_EXPRESSION : EXPAND_NOTHING;
            }
            else if (c != ' ')
            {
--- 1775,1781 ----
            if (c == '&')
            {
                ++xp->xp_pattern;
!               xp->xp_context = has_expr ? EXPAND_EXPRESSION : EXPAND_NOTHING;
            }
            else if (c != ' ')
            {
***************
*** 1792,1798 ****
        }
        else if (c == '=')
        {
!           got_eq = TRUE;
            xp->xp_context = EXPAND_EXPRESSION;
        }
        else if (c == '#'
--- 1792,1798 ----
        }
        else if (c == '=')
        {
!           has_expr = TRUE;
            xp->xp_context = EXPAND_EXPRESSION;
        }
        else if (c == '#'
***************
*** 1808,1814 ****
            // Function name can start with "<SNR>" and contain '#'.
            break;
        }
!       else if (cmdidx != CMD_let || got_eq)
        {
            if (c == '"')           // string
            {
--- 1808,1814 ----
            // Function name can start with "<SNR>" and contain '#'.
            break;
        }
!       else if (has_expr)
        {
            if (c == '"')           // string
            {
*** ../vim-8.2.1743/src/ex_docmd.c      2020-09-23 12:28:46.421898027 +0200
--- src/ex_docmd.c      2020-09-26 12:03:27.813063127 +0200
***************
*** 2421,2426 ****
--- 2421,2427 ----
            case CMD_eval:
            case CMD_execute:
            case CMD_filter:
+           case CMD_final:
            case CMD_help:
            case CMD_hide:
            case CMD_ijump:
***************
*** 2442,2450 ****
            case CMD_noswapfile:
            case CMD_perl:
            case CMD_psearch:
-           case CMD_python:
            case CMD_py3:
            case CMD_python3:
            case CMD_return:
            case CMD_rightbelow:
            case CMD_ruby:
--- 2443,2451 ----
            case CMD_noswapfile:
            case CMD_perl:
            case CMD_psearch:
            case CMD_py3:
            case CMD_python3:
+           case CMD_python:
            case CMD_return:
            case CMD_rightbelow:
            case CMD_ruby:
***************
*** 2460,2465 ****
--- 2461,2467 ----
            case CMD_topleft:
            case CMD_unlet:
            case CMD_unlockvar:
+           case CMD_var:
            case CMD_verbose:
            case CMD_vertical:
            case CMD_wincmd:
***************
*** 3244,3250 ****
                if (skip_expr(&after) == OK
                                  && (*after == '='
                                      || (*after != NUL && after[1] == '=')))
!                   eap->cmdidx = CMD_let;
                else
                    eap->cmdidx = CMD_eval;
                --emsg_silent;
--- 3246,3252 ----
                if (skip_expr(&after) == OK
                                  && (*after == '='
                                      || (*after != NUL && after[1] == '=')))
!                   eap->cmdidx = CMD_var;
                else
                    eap->cmdidx = CMD_eval;
                --emsg_silent;
***************
*** 3268,3274 ****
                }
                if (p > eap->cmd && *skipwhite(p) == '=')
                {
!                   eap->cmdidx = CMD_let;
                    return eap->cmd;
                }
            }
--- 3270,3276 ----
                }
                if (p > eap->cmd && *skipwhite(p) == '=')
                {
!                   eap->cmdidx = CMD_var;
                    return eap->cmd;
                }
            }
***************
*** 3287,3293 ****
                        || *eap->cmd == '@'
                        || lookup(eap->cmd, p - eap->cmd, cctx) != NULL)
                {
!                   eap->cmdidx = CMD_let;
                    return eap->cmd;
                }
            }
--- 3289,3295 ----
                        || *eap->cmd == '@'
                        || lookup(eap->cmd, p - eap->cmd, cctx) != NULL)
                {
!                   eap->cmdidx = CMD_var;
                    return eap->cmd;
                }
            }
*** ../vim-8.2.1743/src/vim9compile.c   2020-09-25 21:47:24.549006886 +0200
--- src/vim9compile.c   2020-09-26 14:12:05.231079989 +0200
***************
*** 4562,4569 ****
  
  /*
   * Compile declaration and assignment:
!  * "let var", "let var = expr", "const var = expr" and "var = expr"
!  * "arg" points to "var".
   * Return NULL for an error.
   * Return "arg" if it does not look like a variable list.
   */
--- 4562,4573 ----
  
  /*
   * Compile declaration and assignment:
!  * "let name"
!  * "var name = expr"
!  * "final name = expr"
!  * "const name = expr"
!  * "name = expr"
!  * "arg" points to "name".
   * Return NULL for an error.
   * Return "arg" if it does not look like a variable list.
   */
***************
*** 4588,4594 ****
      type_T    *member_type = &t_any;
      char_u    *name = NULL;
      char_u    *sp;
!     int               is_decl = cmdidx == CMD_let || cmdidx == CMD_const;
  
      // Skip over the "var" or "[var, var]" to get to any "=".
      p = skip_var_list(arg, TRUE, &var_count, &semicolon, TRUE);
--- 4592,4599 ----
      type_T    *member_type = &t_any;
      char_u    *name = NULL;
      char_u    *sp;
!     int               is_decl = cmdidx == CMD_let || cmdidx == CMD_var
!                                || cmdidx == CMD_final || cmdidx == CMD_const;
  
      // Skip over the "var" or "[var, var]" to get to any "=".
      p = skip_var_list(arg, TRUE, &var_count, &semicolon, TRUE);
***************
*** 4729,4735 ****
                long        numval;
  
                dest = dest_option;
!               if (cmdidx == CMD_const)
                {
                    emsg(_(e_const_option));
                    goto theend;
--- 4734,4740 ----
                long        numval;
  
                dest = dest_option;
!               if (cmdidx == CMD_final || cmdidx == CMD_const)
                {
                    emsg(_(e_const_option));
                    goto theend;
***************
*** 4968,4974 ****
                                            && var_wrong_func_name(name, TRUE))
                goto theend;
            lvar = reserve_local(cctx, var_start, varlen,
!                                                   cmdidx == CMD_const, type);
            if (lvar == NULL)
                goto theend;
            new_local = TRUE;
--- 4973,4979 ----
                                            && var_wrong_func_name(name, TRUE))
                goto theend;
            lvar = reserve_local(cctx, var_start, varlen,
!                            cmdidx == CMD_final || cmdidx == CMD_const, type);
            if (lvar == NULL)
                goto theend;
            new_local = TRUE;
***************
*** 5119,5124 ****
--- 5124,5134 ----
                                                          cctx, FALSE) == FAIL)
                    goto theend;
            }
+           else if (cmdidx == CMD_final)
+           {
+               emsg(_(e_final_requires_a_value));
+               goto theend;
+           }
            else if (cmdidx == CMD_const)
            {
                emsg(_(e_const_requires_a_value));
***************
*** 5283,5291 ****
        }
        else
        {
!           if (is_decl && eap->forceit && cmdidx == CMD_const
!                   && (dest == dest_script || dest == dest_local))
!               // ":const! var": lock the value, but not referenced variables
                generate_LOCKCONST(cctx);
  
            switch (dest)
--- 5293,5301 ----
        }
        else
        {
!           if (is_decl && cmdidx == CMD_const
!                               && (dest == dest_script || dest == dest_local))
!               // ":const var": lock the value, but not referenced variables
                generate_LOCKCONST(cctx);
  
            switch (dest)
***************
*** 6915,6921 ****
            // Expression or function call.
            if (ea.cmdidx != CMD_eval)
            {
!               // CMD_let cannot happen, compile_assignment() above is used
                iemsg("Command from find_ex_command() not handled");
                goto erret;
            }
--- 6925,6931 ----
            // Expression or function call.
            if (ea.cmdidx != CMD_eval)
            {
!               // CMD_var cannot happen, compile_assignment() above is used
                iemsg("Command from find_ex_command() not handled");
                goto erret;
            }
***************
*** 6967,6972 ****
--- 6977,6984 ----
                    break;
  
            case CMD_let:
+           case CMD_var:
+           case CMD_final:
            case CMD_const:
                    line = compile_assignment(p, &ea, ea.cmdidx, &cctx);
                    if (line == p)
*** ../vim-8.2.1743/src/vim9execute.c   2020-09-23 21:57:16.641934712 +0200
--- src/vim9execute.c   2020-09-26 12:18:51.418321945 +0200
***************
*** 729,735 ****
      funccal_entry_T entry;
  
      save_funccal(&entry);
!     set_var_const(name, NULL, tv, FALSE, LET_NO_COMMAND);
      restore_funccal();
  }
  
--- 729,735 ----
      funccal_entry_T entry;
  
      save_funccal(&entry);
!     set_var_const(name, NULL, tv, FALSE, ASSIGN_NO_DECL);
      restore_funccal();
  }
  
*** ../vim-8.2.1743/src/vim9script.c    2020-09-13 18:57:43.514555271 +0200
--- src/vim9script.c    2020-09-26 14:15:59.506188426 +0200
***************
*** 97,102 ****
--- 97,104 ----
      switch (eap->cmdidx)
      {
        case CMD_let:
+       case CMD_var:
+       case CMD_final:
        case CMD_const:
        case CMD_def:
        // case CMD_class:
***************
*** 508,516 ****
      int                   called_emsg_before = called_emsg;
      typval_T      init_tv;
  
!     if (eap->cmdidx == CMD_const)
      {
!       emsg(_(e_const_requires_a_value));
        return arg + STRLEN(arg);
      }
  
--- 510,521 ----
      int                   called_emsg_before = called_emsg;
      typval_T      init_tv;
  
!     if (eap->cmdidx == CMD_final || eap->cmdidx == CMD_const)
      {
!       if (eap->cmdidx == CMD_final)
!           emsg(_(e_final_requires_a_value));
!       else
!           emsg(_(e_const_requires_a_value));
        return arg + STRLEN(arg);
      }
  
*** ../vim-8.2.1743/src/vim.h   2020-09-14 21:38:47.756976285 +0200
--- src/vim.h   2020-09-26 12:23:38.317461276 +0200
***************
*** 2135,2143 ****
  } estack_arg_T;
  
  // Flags for assignment functions.
! #define LET_IS_CONST  1   // ":const"
! #define LET_FORCEIT   2   // ":const!" (LET_IS_CONST is also set)
! #define LET_NO_COMMAND        4   // "var = expr" without ":let" or ":const"
  
  #include "ex_cmds.h"      // Ex command defines
  #include "spell.h"        // spell checking stuff
--- 2135,2143 ----
  } estack_arg_T;
  
  // Flags for assignment functions.
! #define ASSIGN_FINAL  1   // ":final"
! #define ASSIGN_CONST  2   // ":const"
! #define ASSIGN_NO_DECL        4   // "name = expr" without ":let" or ":const"
  
  #include "ex_cmds.h"      // Ex command defines
  #include "spell.h"        // spell checking stuff
*** ../vim-8.2.1743/src/ex_cmdidxs.h    2020-05-24 23:00:06.444196001 +0200
--- src/ex_cmdidxs.h    2020-09-26 13:49:22.066478980 +0200
***************
*** 11,36 ****
    /* d */ 108,
    /* e */ 133,
    /* f */ 156,
!   /* g */ 172,
!   /* h */ 178,
!   /* i */ 187,
!   /* j */ 206,
!   /* k */ 208,
!   /* l */ 213,
!   /* m */ 275,
!   /* n */ 293,
!   /* o */ 313,
!   /* p */ 325,
!   /* q */ 364,
!   /* r */ 367,
!   /* s */ 387,
!   /* t */ 456,
!   /* u */ 501,
!   /* v */ 512,
!   /* w */ 531,
!   /* x */ 545,
!   /* y */ 555,
!   /* z */ 556
  };
  
  /*
--- 11,36 ----
    /* d */ 108,
    /* e */ 133,
    /* f */ 156,
!   /* g */ 173,
!   /* h */ 179,
!   /* i */ 188,
!   /* j */ 207,
!   /* k */ 209,
!   /* l */ 214,
!   /* m */ 276,
!   /* n */ 294,
!   /* o */ 314,
!   /* p */ 326,
!   /* q */ 365,
!   /* r */ 368,
!   /* s */ 388,
!   /* t */ 457,
!   /* u */ 502,
!   /* v */ 513,
!   /* w */ 533,
!   /* x */ 547,
!   /* y */ 557,
!   /* z */ 558
  };
  
  /*
***************
*** 46,52 ****
    /* c */ {  3, 12, 16, 18, 20, 22, 25,  0,  0,  0,  0, 33, 37, 40, 46, 56, 
58, 59, 60,  0, 62,  0, 65,  0,  0,  0 },
    /* d */ {  0,  0,  0,  0,  0,  0,  0,  0,  8, 18,  0, 19,  0,  0, 20,  0,  
0, 22, 23,  0,  0,  0,  0,  0,  0,  0 },
    /* e */ {  1,  0,  2,  0,  0,  0,  0,  0,  0,  0,  0,  7,  9, 10,  0,  0,  
0,  0,  0,  0,  0, 17,  0, 18,  0,  0 },
!   /* f */ {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  9,  0,  
0,  0,  0,  0, 15,  0,  0,  0,  0,  0 },
    /* g */ {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  
0,  2,  0,  0,  4,  5,  0,  0,  0,  0 },
    /* h */ {  5,  0,  0,  0,  0,  0,  0,  0,  6,  0,  0,  0,  0,  0,  0,  0,  
0,  0,  0,  0,  0,  0,  0,  0,  0,  0 },
    /* i */ {  1,  0,  0,  0,  0,  3,  0,  0,  0,  4,  0,  5,  6,  0,  0,  0,  
0,  0, 14,  0, 16,  0,  0,  0,  0,  0 },
--- 46,52 ----
    /* c */ {  3, 12, 16, 18, 20, 22, 25,  0,  0,  0,  0, 33, 37, 40, 46, 56, 
58, 59, 60,  0, 62,  0, 65,  0,  0,  0 },
    /* d */ {  0,  0,  0,  0,  0,  0,  0,  0,  8, 18,  0, 19,  0,  0, 20,  0,  
0, 22, 23,  0,  0,  0,  0,  0,  0,  0 },
    /* e */ {  1,  0,  2,  0,  0,  0,  0,  0,  0,  0,  0,  7,  9, 10,  0,  0,  
0,  0,  0,  0,  0, 17,  0, 18,  0,  0 },
!   /* f */ {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 10,  0,  
0,  0,  0,  0, 16,  0,  0,  0,  0,  0 },
    /* g */ {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  
0,  2,  0,  0,  4,  5,  0,  0,  0,  0 },
    /* h */ {  5,  0,  0,  0,  0,  0,  0,  0,  6,  0,  0,  0,  0,  0,  0,  0,  
0,  0,  0,  0,  0,  0,  0,  0,  0,  0 },
    /* i */ {  1,  0,  0,  0,  0,  3,  0,  0,  0,  4,  0,  5,  6,  0,  0,  0,  
0,  0, 14,  0, 16,  0,  0,  0,  0,  0 },
***************
*** 62,72 ****
    /* s */ {  2,  6, 15,  0, 19, 23,  0, 25, 26,  0,  0, 29, 31, 35, 39, 41,  
0, 50,  0, 51,  0, 63, 64,  0, 65,  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,  0,  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 */ {  0,  0,  0,  0,  1,  0,  0,  0,  4,  0,  0,  0, 10, 13,  0,  0,  
0,  0, 16,  0, 17,  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 },
    /* x */ {  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  2,  5,  0,  0,  
0,  7,  0,  0,  8,  0,  0,  0,  0,  0 },
    /* y */ {  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 },
    /* 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 = 569;
--- 62,72 ----
    /* s */ {  2,  6, 15,  0, 19, 23,  0, 25, 26,  0,  0, 29, 31, 35, 39, 41,  
0, 50,  0, 51,  0, 63, 64,  0, 65,  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,  0,  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, 11, 14,  0,  0,  
0,  0, 17,  0, 18,  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 },
    /* x */ {  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  2,  5,  0,  0,  
0,  7,  0,  0,  8,  0,  0,  0,  0,  0 },
    /* y */ {  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 },
    /* 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 = 571;
*** ../vim-8.2.1743/src/testdir/test_vim9_assign.vim    2020-09-23 
15:56:47.132579290 +0200
--- src/testdir/test_vim9_assign.vim    2020-09-26 14:47:45.384867462 +0200
***************
*** 12,41 ****
  let g:astring = 'text'
  
  def Test_assignment_bool()
!   let bool1: bool = true
    assert_equal(v:true, bool1)
!   let bool2: bool = false
    assert_equal(v:false, bool2)
  
!   let bool3: bool = 0
    assert_equal(false, bool3)
!   let bool4: bool = 1
    assert_equal(true, bool4)
  
!   let bool5: bool = 'yes' && 'no'
    assert_equal(true, bool5)
!   let bool6: bool = [] && 99
    assert_equal(false, bool6)
!   let bool7: bool = [] || #{a: 1} && 99
    assert_equal(true, bool7)
  
!   let lines =<< trim END
      vim9script
      def GetFlag(): bool
!       let flag: bool = 1
        return flag
      enddef
!     let flag: bool = GetFlag()
      assert_equal(true, flag)
      flag = 0
      assert_equal(false, flag)
--- 12,41 ----
  let g:astring = 'text'
  
  def Test_assignment_bool()
!   var bool1: bool = true
    assert_equal(v:true, bool1)
!   var bool2: bool = false
    assert_equal(v:false, bool2)
  
!   var bool3: bool = 0
    assert_equal(false, bool3)
!   var bool4: bool = 1
    assert_equal(true, bool4)
  
!   var bool5: bool = 'yes' && 'no'
    assert_equal(true, bool5)
!   var bool6: bool = [] && 99
    assert_equal(false, bool6)
!   var bool7: bool = [] || #{a: 1} && 99
    assert_equal(true, bool7)
  
!   var lines =<< trim END
      vim9script
      def GetFlag(): bool
!       var flag: bool = 1
        return flag
      enddef
!     var flag: bool = GetFlag()
      assert_equal(true, flag)
      flag = 0
      assert_equal(false, flag)
***************
*** 47,87 ****
      assert_equal(false, flag)
    END
    CheckScriptSuccess(lines)
!   CheckDefAndScriptFailure(['let x: bool = 2'], 'E1012:')
!   CheckDefAndScriptFailure(['let x: bool = -1'], 'E1012:')
!   CheckDefAndScriptFailure(['let x: bool = [1]'], 'E1012:')
!   CheckDefAndScriptFailure(['let x: bool = {}'], 'E1012:')
!   CheckDefAndScriptFailure(['let x: bool = "x"'], 'E1012:')
  enddef
  
  def Test_syntax()
!   let var = 234
!   let other: list<string> = ['asdf']
  enddef
  
  def Test_assignment()
!   CheckDefFailure(['let x:string'], 'E1069:')
!   CheckDefFailure(['let x:string = "x"'], 'E1069:')
!   CheckDefFailure(['let a:string = "x"'], 'E1069:')
!   CheckDefFailure(['let lambda = {-> "lambda"}'], 'E704:')
  
!   let nr: number = 1234
!   CheckDefFailure(['let nr: number = "asdf"'], 'E1012:')
  
!   let a: number = 6 #comment
    assert_equal(6, a)
  
    if has('channel')
!     let chan1: channel
!     let job1: job
!     let job2: job = job_start('willfail')
    endif
    if has('float')
!     let float1: float = 3.4
    endif
!   let Funky1: func
!   let Funky2: func = function('len')
!   let Party2: func = funcref('g:Test_syntax')
  
    g:newvar = 'new'  #comment
    assert_equal('new', g:newvar)
--- 47,88 ----
      assert_equal(false, flag)
    END
    CheckScriptSuccess(lines)
!   CheckDefAndScriptFailure(['var x: bool = 2'], 'E1012:')
!   CheckDefAndScriptFailure(['var x: bool = -1'], 'E1012:')
!   CheckDefAndScriptFailure(['var x: bool = [1]'], 'E1012:')
!   CheckDefAndScriptFailure(['var x: bool = {}'], 'E1012:')
!   CheckDefAndScriptFailure(['var x: bool = "x"'], 'E1012:')
  enddef
  
  def Test_syntax()
!   var var = 234
!   var other: list<string> = ['asdf']
  enddef
  
  def Test_assignment()
!   CheckDefFailure(['var x:string'], 'E1069:')
!   CheckDefFailure(['var x:string = "x"'], 'E1069:')
!   CheckDefFailure(['var a:string = "x"'], 'E1069:')
!   CheckDefFailure(['var lambda = {-> "lambda"}'], 'E704:')
!   CheckScriptFailure(['var x = "x"'], 'E1124:')
  
!   var nr: number = 1234
!   CheckDefFailure(['var nr: number = "asdf"'], 'E1012:')
  
!   var a: number = 6 #comment
    assert_equal(6, a)
  
    if has('channel')
!     var chan1: channel
!     var job1: job
!     var job2: job = job_start('willfail')
    endif
    if has('float')
!     var float1: float = 3.4
    endif
!   var Funky1: func
!   var Funky2: func = function('len')
!   var Party2: func = funcref('g:Test_syntax')
  
    g:newvar = 'new'  #comment
    assert_equal('new', g:newvar)
***************
*** 97,103 ****
    assert_equal('foobar', $ENVVAR)
    $ENVVAR = ''
  
!   let lines =<< trim END
      vim9script
      $ENVVAR = 'barfoo'
      assert_equal('barfoo', $ENVVAR)
--- 98,104 ----
    assert_equal('foobar', $ENVVAR)
    $ENVVAR = ''
  
!   var lines =<< trim END
      vim9script
      $ENVVAR = 'barfoo'
      assert_equal('barfoo', $ENVVAR)
***************
*** 126,140 ****
    assert_equal(2, &ts)
  
    if has('float')
!     let f100: float = 100.0
      f100 /= 5
      assert_equal(20.0, f100)
  
!     let f200: float = 200.0
      f200 /= 5.0
      assert_equal(40.0, f200)
  
!     CheckDefFailure(['let nr: number = 200', 'nr /= 5.0'], 'E1012:')
    endif
  
    lines =<< trim END
--- 127,141 ----
    assert_equal(2, &ts)
  
    if has('float')
!     var f100: float = 100.0
      f100 /= 5
      assert_equal(20.0, f100)
  
!     var f200: float = 200.0
      f200 /= 5.0
      assert_equal(40.0, f200)
  
!     CheckDefFailure(['var nr: number = 200', 'nr /= 5.0'], 'E1012:')
    endif
  
    lines =<< trim END
***************
*** 163,173 ****
    CheckDefFailure(['&path += 3'], 'E1012:')
    CheckDefExecFailure(['&bs = "asdf"'], 'E474:')
    # test freeing ISN_STOREOPT
!   CheckDefFailure(['&ts = 3', 'let asdf'], 'E1022:')
    &ts = 8
  
    lines =<< trim END
!     let save_TI = &t_TI
      &t_TI = ''
      assert_equal('', &t_TI)
      &t_TI = 'xxx'
--- 164,174 ----
    CheckDefFailure(['&path += 3'], 'E1012:')
    CheckDefExecFailure(['&bs = "asdf"'], 'E474:')
    # test freeing ISN_STOREOPT
!   CheckDefFailure(['&ts = 3', 'var asdf'], 'E1022:')
    &ts = 8
  
    lines =<< trim END
!     var save_TI = &t_TI
      &t_TI = ''
      assert_equal('', &t_TI)
      &t_TI = 'xxx'
***************
*** 179,186 ****
    CheckDefFailure(['&t_TI = 123'], 'E1012:')
    CheckScriptFailure(['vim9script', '&t_TI = 123'], 'E928:')
  
!   CheckDefFailure(['let s:var = 123'], 'E1101:')
!   CheckDefFailure(['let s:var: number'], 'E1101:')
  
    lines =<< trim END
      vim9script
--- 180,187 ----
    CheckDefFailure(['&t_TI = 123'], 'E1012:')
    CheckScriptFailure(['vim9script', '&t_TI = 123'], 'E928:')
  
!   CheckDefFailure(['var s:var = 123'], 'E1101:')
!   CheckDefFailure(['var s:var: number'], 'E1101:')
  
    lines =<< trim END
      vim9script
***************
*** 217,236 ****
  
    # this should not leak
    if 0
!     let text =<< trim END
        some text
      END
    endif
  enddef
  
  def Test_extend_list()
!   let lines =<< trim END
        vim9script
!       let l: list<number>
        l += [123]
        assert_equal([123], l)
  
!       let d: dict<number>
        d['one'] = 1
        assert_equal(#{one: 1}, d)
    END
--- 218,237 ----
  
    # this should not leak
    if 0
!     var text =<< trim END
        some text
      END
    endif
  enddef
  
  def Test_extend_list()
!   var lines =<< trim END
        vim9script
!       var l: list<number>
        l += [123]
        assert_equal([123], l)
  
!       var d: dict<number>
        d['one'] = 1
        assert_equal(#{one: 1}, d)
    END
***************
*** 239,279 ****
  
  def Test_single_letter_vars()
    # single letter variables
!   let a: number = 123
    a = 123
    assert_equal(123, a)
!   let b: number
    b = 123
    assert_equal(123, b)
!   let g: number
    g = 123
    assert_equal(123, g)
!   let s: number
    s = 123
    assert_equal(123, s)
!   let t: number
    t = 123
    assert_equal(123, t)
!   let v: number
    v = 123
    assert_equal(123, v)
!   let w: number
    w = 123
    assert_equal(123, w)
  enddef
  
  def Test_vim9_single_char_vars()
!   let lines =<< trim END
        vim9script
  
        # single character variable declarations work
!       let a: string
!       let b: number
!       let l: list<any>
!       let s: string
!       let t: number
!       let v: number
!       let w: number
  
        # script-local variables can be used without s: prefix
        a = 'script-a'
--- 240,280 ----
  
  def Test_single_letter_vars()
    # single letter variables
!   var a: number = 123
    a = 123
    assert_equal(123, a)
!   var b: number
    b = 123
    assert_equal(123, b)
!   var g: number
    g = 123
    assert_equal(123, g)
!   var s: number
    s = 123
    assert_equal(123, s)
!   var t: number
    t = 123
    assert_equal(123, t)
!   var v: number
    v = 123
    assert_equal(123, v)
!   var w: number
    w = 123
    assert_equal(123, w)
  enddef
  
  def Test_vim9_single_char_vars()
!   var lines =<< trim END
        vim9script
  
        # single character variable declarations work
!       var a: string
!       var b: number
!       var l: list<any>
!       var s: string
!       var t: number
!       var v: number
!       var w: number
  
        # script-local variables can be used without s: prefix
        a = 'script-a'
***************
*** 298,311 ****
  enddef
  
  def Test_assignment_list()
!   let list1: list<bool> = [false, true, false]
!   let list2: list<number> = [1, 2, 3]
!   let list3: list<string> = ['sdf', 'asdf']
!   let list4: list<any> = ['yes', true, 1234]
!   let list5: list<blob> = [0z01, 0z02]
  
!   let listS: list<string> = []
!   let listN: list<number> = []
  
    assert_equal([1, 2, 3], list2)
    list2[-1] = 99
--- 299,312 ----
  enddef
  
  def Test_assignment_list()
!   var list1: list<bool> = [false, true, false]
!   var list2: list<number> = [1, 2, 3]
!   var list3: list<string> = ['sdf', 'asdf']
!   var list4: list<any> = ['yes', true, 1234]
!   var list5: list<blob> = [0z01, 0z02]
  
!   var listS: list<string> = []
!   var listN: list<number> = []
  
    assert_equal([1, 2, 3], list2)
    list2[-1] = 99
***************
*** 320,338 ****
    list3 += ['end']
    assert_equal(['sdf', 'asdf', 'end'], list3)
  
!   CheckDefExecFailure(['let ll = [1, 2, 3]', 'll[-4] = 6'], 'E684:')
!   CheckDefExecFailure(['let [v1, v2] = [1, 2]'], 'E1092:')
  
    # type becomes list<any>
!   let somelist = rand() > 0 ? [1, 2, 3] : ['a', 'b', 'c']
  enddef
  
  def Test_assignment_list_vim9script()
!   let lines =<< trim END
      vim9script
!     let v1: number
!     let v2: number
!     let v3: number
      [v1, v2, v3] = [1, 2, 3]
      assert_equal([1, 2, 3], [v1, v2, v3])
    END
--- 321,339 ----
    list3 += ['end']
    assert_equal(['sdf', 'asdf', 'end'], list3)
  
!   CheckDefExecFailure(['var ll = [1, 2, 3]', 'll[-4] = 6'], 'E684:')
!   CheckDefExecFailure(['var [v1, v2] = [1, 2]'], 'E1092:')
  
    # type becomes list<any>
!   var somelist = rand() > 0 ? [1, 2, 3] : ['a', 'b', 'c']
  enddef
  
  def Test_assignment_list_vim9script()
!   var lines =<< trim END
      vim9script
!     var v1: number
!     var v2: number
!     var v3: number
      [v1, v2, v3] = [1, 2, 3]
      assert_equal([1, 2, 3], [v1, v2, v3])
    END
***************
*** 340,366 ****
  enddef
  
  def Test_assignment_dict()
!   let dict1: dict<bool> = #{one: false, two: true}
!   let dict2: dict<number> = #{one: 1, two: 2}
!   let dict3: dict<string> = #{key: 'value'}
!   let dict4: dict<any> = #{one: 1, two: '2'}
!   let dict5: dict<blob> = #{one: 0z01, two: 0z02}
  
    # overwrite
    dict3['key'] = 'another'
  
    # empty key can be used
!   let dd = {}
    dd[""] = 6
    assert_equal({'': 6}, dd)
  
    # type becomes dict<any>
!   let somedict = rand() > 0 ? #{a: 1, b: 2} : #{a: 'a', b: 'b'}
  
    # assignment to script-local dict
!   let lines =<< trim END
      vim9script
!     let test: dict<any> = {}
      def FillDict(): dict<any>
        test['a'] = 43
        return test
--- 341,367 ----
  enddef
  
  def Test_assignment_dict()
!   var dict1: dict<bool> = #{one: false, two: true}
!   var dict2: dict<number> = #{one: 1, two: 2}
!   var dict3: dict<string> = #{key: 'value'}
!   var dict4: dict<any> = #{one: 1, two: '2'}
!   var dict5: dict<blob> = #{one: 0z01, two: 0z02}
  
    # overwrite
    dict3['key'] = 'another'
  
    # empty key can be used
!   var dd = {}
    dd[""] = 6
    assert_equal({'': 6}, dd)
  
    # type becomes dict<any>
!   var somedict = rand() > 0 ? #{a: 1, b: 2} : #{a: 'a', b: 'b'}
  
    # assignment to script-local dict
!   var lines =<< trim END
      vim9script
!     var test: dict<any> = {}
      def FillDict(): dict<any>
        test['a'] = 43
        return test
***************
*** 371,377 ****
  
    lines =<< trim END
      vim9script
!     let test: dict<any>
      def FillDict(): dict<any>
        test['a'] = 43
        return test
--- 372,378 ----
  
    lines =<< trim END
      vim9script
!     var test: dict<any>
      def FillDict(): dict<any>
        test['a'] = 43
        return test
***************
*** 408,414 ****
  def Test_assignment_local()
    # Test in a separated file in order not to the current buffer/window/tab is
    # changed.
!   let script_lines: list<string> =<< trim END
      let b:existing = 'yes'
      let w:existing = 'yes'
      let t:existing = 'yes'
--- 409,415 ----
  def Test_assignment_local()
    # Test in a separated file in order not to the current buffer/window/tab is
    # changed.
!   var script_lines: list<string> =<< trim END
      let b:existing = 'yes'
      let w:existing = 'yes'
      let t:existing = 'yes'
***************
*** 446,482 ****
  def Test_assignment_default()
  
    # Test default values.
!   let thebool: bool
    assert_equal(v:false, thebool)
  
!   let thenumber: number
    assert_equal(0, thenumber)
  
    if has('float')
!     let thefloat: float
      assert_equal(0.0, thefloat)
    endif
  
!   let thestring: string
    assert_equal('', thestring)
  
!   let theblob: blob
    assert_equal(0z, theblob)
  
!   let Thefunc: func
    assert_equal(test_null_function(), Thefunc)
  
!   let thelist: list<any>
    assert_equal([], thelist)
  
!   let thedict: dict<any>
    assert_equal({}, thedict)
  
    if has('channel')
!     let thejob: job
      assert_equal(test_null_job(), thejob)
  
!     let thechannel: channel
      assert_equal(test_null_channel(), thechannel)
  
      if has('unix') && executable('cat')
--- 447,483 ----
  def Test_assignment_default()
  
    # Test default values.
!   var thebool: bool
    assert_equal(v:false, thebool)
  
!   var thenumber: number
    assert_equal(0, thenumber)
  
    if has('float')
!     var thefloat: float
      assert_equal(0.0, thefloat)
    endif
  
!   var thestring: string
    assert_equal('', thestring)
  
!   var theblob: blob
    assert_equal(0z, theblob)
  
!   var Thefunc: func
    assert_equal(test_null_function(), Thefunc)
  
!   var thelist: list<any>
    assert_equal([], thelist)
  
!   var thedict: dict<any>
    assert_equal({}, thedict)
  
    if has('channel')
!     var thejob: job
      assert_equal(test_null_job(), thejob)
  
!     var thechannel: channel
      assert_equal(test_null_channel(), thechannel)
  
      if has('unix') && executable('cat')
***************
*** 487,500 ****
      endif
    endif
  
!   let nr = 1234 | nr = 5678
    assert_equal(5678, nr)
  enddef
  
  def Test_assignment_var_list()
!   let v1: string
!   let v2: string
!   let vrem: list<string>
    [v1] = ['aaa']
    assert_equal('aaa', v1)
  
--- 488,501 ----
      endif
    endif
  
!   var nr = 1234 | nr = 5678
    assert_equal(5678, nr)
  enddef
  
  def Test_assignment_var_list()
!   var v1: string
!   var v2: string
!   var vrem: list<string>
    [v1] = ['aaa']
    assert_equal('aaa', v1)
  
***************
*** 519,536 ****
  enddef
  
  def Test_assignment_vim9script()
!   let lines =<< trim END
      vim9script
      def Func(): list<number>
        return [1, 2]
      enddef
!     let var1: number
!     let var2: number
      [var1, var2] =
            Func()
      assert_equal(1, var1)
      assert_equal(2, var2)
!     let ll =
            Func()
      assert_equal([1, 2], ll)
  
--- 520,537 ----
  enddef
  
  def Test_assignment_vim9script()
!   var lines =<< trim END
      vim9script
      def Func(): list<number>
        return [1, 2]
      enddef
!     var var1: number
!     var var2: number
      [var1, var2] =
            Func()
      assert_equal(1, var1)
      assert_equal(2, var2)
!     var ll =
            Func()
      assert_equal([1, 2], ll)
  
***************
*** 551,565 ****
        assert_equal('plus', @+)
      endif
  
!     let a: number = 123
      assert_equal(123, a)
!     let s: string = 'yes'
      assert_equal('yes', s)
!     let b: number = 42
      assert_equal(42, b)
!     let w: number = 43
      assert_equal(43, w)
!     let t: number = 44
      assert_equal(44, t)
    END
    CheckScriptSuccess(lines)
--- 552,566 ----
        assert_equal('plus', @+)
      endif
  
!     var a: number = 123
      assert_equal(123, a)
!     var s: string = 'yes'
      assert_equal('yes', s)
!     var b: number = 42
      assert_equal(42, b)
!     var w: number = 43
      assert_equal(43, w)
!     var t: number = 44
      assert_equal(44, t)
    END
    CheckScriptSuccess(lines)
***************
*** 571,650 ****
  enddef
  
  def Test_assignment_failure()
!   CheckDefFailure(['let var=234'], 'E1004:')
!   CheckDefFailure(['let var =234'], 'E1004:')
!   CheckDefFailure(['let var= 234'], 'E1004:')
! 
!   CheckScriptFailure(['vim9script', 'let var=234'], 'E1004:')
!   CheckScriptFailure(['vim9script', 'let var=234'], "before and after '='")
!   CheckScriptFailure(['vim9script', 'let var =234'], 'E1004:')
!   CheckScriptFailure(['vim9script', 'let var= 234'], 'E1004:')
!   CheckScriptFailure(['vim9script', 'let var = 234', 'var+=234'], 'E1004:')
!   CheckScriptFailure(['vim9script', 'let var = 234', 'var+=234'], "before and 
after '+='")
!   CheckScriptFailure(['vim9script', 'let var = "x"', 'var..="y"'], 'E1004:')
!   CheckScriptFailure(['vim9script', 'let var = "x"', 'var..="y"'], "before 
and after '..='")
  
!   CheckDefFailure(['let true = 1'], 'E1034:')
!   CheckDefFailure(['let false = 1'], 'E1034:')
  
    CheckDefFailure(['[a; b; c] = g:list'], 'E452:')
!   CheckDefExecFailure(['let a: number',
                         '[a] = test_null_list()'], 'E1093:')
!   CheckDefExecFailure(['let a: number',
                         '[a] = []'], 'E1093:')
!   CheckDefExecFailure(['let x: number',
!                        'let y: number',
                         '[x, y] = [1]'], 'E1093:')
!   CheckDefExecFailure(['let x: number',
!                        'let y: number',
!                        'let z: list<number>',
                         '[x, y; z] = [1]'], 'E1093:')
  
!   CheckDefFailure(['let somevar'], "E1022:")
!   CheckDefFailure(['let &tabstop = 4'], 'E1052:')
    CheckDefFailure(['&g:option = 5'], 'E113:')
!   CheckScriptFailure(['vim9script', 'let &tabstop = 4'], 'E1052:')
  
!   CheckDefFailure(['let $VAR = 5'], 'E1016: Cannot declare an environment 
variable:')
!   CheckScriptFailure(['vim9script', 'let $ENV = "xxx"'], 'E1016:')
  
    if has('dnd')
!     CheckDefFailure(['let @~ = 5'], 'E1066:')
    else
!     CheckDefFailure(['let @~ = 5'], 'E354:')
      CheckDefFailure(['@~ = 5'], 'E354:')
    endif
!   CheckDefFailure(['let @a = 5'], 'E1066:')
!   CheckDefFailure(['let @/ = "x"'], 'E1066:')
!   CheckScriptFailure(['vim9script', 'let @a = "abc"'], 'E1066:')
! 
!   CheckDefFailure(['let g:var = 5'], 'E1016: Cannot declare a global 
variable:')
!   CheckDefFailure(['let w:var = 5'], 'E1016: Cannot declare a window 
variable:')
!   CheckDefFailure(['let b:var = 5'], 'E1016: Cannot declare a buffer 
variable:')
!   CheckDefFailure(['let t:var = 5'], 'E1016: Cannot declare a tab variable:')
! 
!   CheckDefFailure(['let anr = 4', 'anr ..= "text"'], 'E1019:')
!   CheckDefFailure(['let xnr += 4'], 'E1020:', 1)
!   CheckScriptFailure(['vim9script', 'let xnr += 4'], 'E1020:')
!   CheckDefFailure(["let xnr = xnr + 1"], 'E1001:', 1)
!   CheckScriptFailure(['vim9script', 'let xnr = xnr + 4'], 'E121:')
! 
!   CheckScriptFailure(['vim9script', 'def Func()', 'let dummy = s:notfound', 
'enddef', 'defcompile'], 'E1108:')
! 
!   CheckDefFailure(['let var: list<string> = [123]'], 'expected list<string> 
but got list<number>')
!   CheckDefFailure(['let var: list<number> = ["xx"]'], 'expected list<number> 
but got list<string>')
  
!   CheckDefFailure(['let var: dict<string> = #{key: 123}'], 'expected 
dict<string> but got dict<number>')
!   CheckDefFailure(['let var: dict<number> = #{key: "xx"}'], 'expected 
dict<number> but got dict<string>')
  
!   CheckDefFailure(['let var = feedkeys("0")'], 'E1031:')
!   CheckDefFailure(['let var: number = feedkeys("0")'], 'expected number but 
got void')
  
!   CheckDefFailure(['let var: dict <number>'], 'E1068:')
!   CheckDefFailure(['let var: dict<number'], 'E1009:')
  
    assert_fails('s/^/\=Mess()/n', 'E794:')
!   CheckDefFailure(['let var: dict<number'], 'E1009:')
  
    CheckDefFailure(['w:foo: number = 10'],
                    'E488: Trailing characters: : number = 1')
--- 572,651 ----
  enddef
  
  def Test_assignment_failure()
!   CheckDefFailure(['var var=234'], 'E1004:')
!   CheckDefFailure(['var var =234'], 'E1004:')
!   CheckDefFailure(['var var= 234'], 'E1004:')
! 
!   CheckScriptFailure(['vim9script', 'var var=234'], 'E1004:')
!   CheckScriptFailure(['vim9script', 'var var=234'], "before and after '='")
!   CheckScriptFailure(['vim9script', 'var var =234'], 'E1004:')
!   CheckScriptFailure(['vim9script', 'var var= 234'], 'E1004:')
!   CheckScriptFailure(['vim9script', 'var var = 234', 'var+=234'], 'E1004:')
!   CheckScriptFailure(['vim9script', 'var var = 234', 'var+=234'], "before and 
after '+='")
!   CheckScriptFailure(['vim9script', 'var var = "x"', 'var..="y"'], 'E1004:')
!   CheckScriptFailure(['vim9script', 'var var = "x"', 'var..="y"'], "before 
and after '..='")
  
!   CheckDefFailure(['var true = 1'], 'E1034:')
!   CheckDefFailure(['var false = 1'], 'E1034:')
  
    CheckDefFailure(['[a; b; c] = g:list'], 'E452:')
!   CheckDefExecFailure(['var a: number',
                         '[a] = test_null_list()'], 'E1093:')
!   CheckDefExecFailure(['var a: number',
                         '[a] = []'], 'E1093:')
!   CheckDefExecFailure(['var x: number',
!                        'var y: number',
                         '[x, y] = [1]'], 'E1093:')
!   CheckDefExecFailure(['var x: number',
!                        'var y: number',
!                        'var z: list<number>',
                         '[x, y; z] = [1]'], 'E1093:')
  
!   CheckDefFailure(['var somevar'], "E1022:")
!   CheckDefFailure(['var &tabstop = 4'], 'E1052:')
    CheckDefFailure(['&g:option = 5'], 'E113:')
!   CheckScriptFailure(['vim9script', 'var &tabstop = 4'], 'E1052:')
  
!   CheckDefFailure(['var $VAR = 5'], 'E1016: Cannot declare an environment 
variable:')
!   CheckScriptFailure(['vim9script', 'var $ENV = "xxx"'], 'E1016:')
  
    if has('dnd')
!     CheckDefFailure(['var @~ = 5'], 'E1066:')
    else
!     CheckDefFailure(['var @~ = 5'], 'E354:')
      CheckDefFailure(['@~ = 5'], 'E354:')
    endif
!   CheckDefFailure(['var @a = 5'], 'E1066:')
!   CheckDefFailure(['var @/ = "x"'], 'E1066:')
!   CheckScriptFailure(['vim9script', 'var @a = "abc"'], 'E1066:')
! 
!   CheckDefFailure(['var g:var = 5'], 'E1016: Cannot declare a global 
variable:')
!   CheckDefFailure(['var w:var = 5'], 'E1016: Cannot declare a window 
variable:')
!   CheckDefFailure(['var b:var = 5'], 'E1016: Cannot declare a buffer 
variable:')
!   CheckDefFailure(['var t:var = 5'], 'E1016: Cannot declare a tab variable:')
! 
!   CheckDefFailure(['var anr = 4', 'anr ..= "text"'], 'E1019:')
!   CheckDefFailure(['var xnr += 4'], 'E1020:', 1)
!   CheckScriptFailure(['vim9script', 'var xnr += 4'], 'E1020:')
!   CheckDefFailure(["var xnr = xnr + 1"], 'E1001:', 1)
!   CheckScriptFailure(['vim9script', 'var xnr = xnr + 4'], 'E121:')
! 
!   CheckScriptFailure(['vim9script', 'def Func()', 'var dummy = s:notfound', 
'enddef', 'defcompile'], 'E1108:')
! 
!   CheckDefFailure(['var var: list<string> = [123]'], 'expected list<string> 
but got list<number>')
!   CheckDefFailure(['var var: list<number> = ["xx"]'], 'expected list<number> 
but got list<string>')
  
!   CheckDefFailure(['var var: dict<string> = #{key: 123}'], 'expected 
dict<string> but got dict<number>')
!   CheckDefFailure(['var var: dict<number> = #{key: "xx"}'], 'expected 
dict<number> but got dict<string>')
  
!   CheckDefFailure(['var var = feedkeys("0")'], 'E1031:')
!   CheckDefFailure(['var var: number = feedkeys("0")'], 'expected number but 
got void')
  
!   CheckDefFailure(['var var: dict <number>'], 'E1068:')
!   CheckDefFailure(['var var: dict<number'], 'E1009:')
  
    assert_fails('s/^/\=Mess()/n', 'E794:')
!   CheckDefFailure(['var var: dict<number'], 'E1009:')
  
    CheckDefFailure(['w:foo: number = 10'],
                    'E488: Trailing characters: : number = 1')
***************
*** 657,663 ****
  enddef
  
  def Test_assign_list()
!   let l: list<string> = []
    l[0] = 'value'
    assert_equal('value', l[0])
  
--- 658,664 ----
  enddef
  
  def Test_assign_list()
!   var l: list<string> = []
    l[0] = 'value'
    assert_equal('value', l[0])
  
***************
*** 667,673 ****
    assert_equal('asdf', l[-1])
    assert_equal('value', l[-2])
  
!   let nrl: list<number> = []
    for i in range(5)
      nrl[i] = i
    endfor
--- 668,674 ----
    assert_equal('asdf', l[-1])
    assert_equal('value', l[-2])
  
!   var nrl: list<number> = []
    for i in range(5)
      nrl[i] = i
    endfor
***************
*** 675,681 ****
  enddef
  
  def Test_assign_dict()
!   let d: dict<string> = {}
    d['key'] = 'value'
    assert_equal('value', d['key'])
  
--- 676,682 ----
  enddef
  
  def Test_assign_dict()
!   var d: dict<string> = {}
    d['key'] = 'value'
    assert_equal('value', d['key'])
  
***************
*** 683,689 ****
    assert_equal('qwerty', d[123])
    assert_equal('qwerty', d['123'])
  
!   let nrd: dict<number> = {}
    for i in range(3)
      nrd[i] = i
    endfor
--- 684,690 ----
    assert_equal('qwerty', d[123])
    assert_equal('qwerty', d['123'])
  
!   var nrd: dict<number> = {}
    for i in range(3)
      nrd[i] = i
    endfor
***************
*** 691,702 ****
  enddef
  
  def Test_assign_dict_unknown_type()
!   let lines =<< trim END
        vim9script
!       let mylist = []
        mylist += [#{one: 'one'}]
        def Func()
!         let dd = mylist[0]
          assert_equal('one', dd.one)
        enddef
        Func()
--- 692,703 ----
  enddef
  
  def Test_assign_dict_unknown_type()
!   var lines =<< trim END
        vim9script
!       var mylist = []
        mylist += [#{one: 'one'}]
        def Func()
!         var dd = mylist[0]
          assert_equal('one', dd.one)
        enddef
        Func()
***************
*** 706,715 ****
    # doesn't work yet
    #lines =<< trim END
    #    vim9script
!   #    let mylist = [[]]
    #    mylist[0] += [#{one: 'one'}]
    #    def Func()
!   #      let dd = mylist[0][0]
    #      assert_equal('one', dd.one)
    #    enddef
    #    Func()
--- 707,716 ----
    # doesn't work yet
    #lines =<< trim END
    #    vim9script
!   #    var mylist = [[]]
    #    mylist[0] += [#{one: 'one'}]
    #    def Func()
!   #      var dd = mylist[0][0]
    #      assert_equal('one', dd.one)
    #    enddef
    #    Func()
***************
*** 719,731 ****
  
  def Test_assign_lambda()
    # check if assign a lambda to a variable which type is func or any.
!   let lines =<< trim END
        vim9script
!       let FuncRef = {->123}
        assert_equal(123, FuncRef())
!       let FuncRef_Func: func = {->123}
        assert_equal(123, FuncRef_Func())
!       let FuncRef_Any: any = {->123}
        assert_equal(123, FuncRef_Any())
    END
    CheckScriptSuccess(lines)
--- 720,732 ----
  
  def Test_assign_lambda()
    # check if assign a lambda to a variable which type is func or any.
!   var lines =<< trim END
        vim9script
!       var FuncRef = {->123}
        assert_equal(123, FuncRef())
!       var FuncRef_Func: func = {->123}
        assert_equal(123, FuncRef_Func())
!       var FuncRef_Any: any = {->123}
        assert_equal(123, FuncRef_Any())
    END
    CheckScriptSuccess(lines)
*** ../vim-8.2.1743/src/testdir/test_vim9_script.vim    2020-09-25 
23:12:47.835917573 +0200
--- src/testdir/test_vim9_script.vim    2020-09-26 14:16:29.102084153 +0200
***************
*** 193,213 ****
  enddef
  
  def Test_const()
!   CheckDefFailure(['const var = 234', 'var = 99'], 'E1018:')
!   CheckDefFailure(['const one = 234', 'let one = 99'], 'E1017:')
!   CheckDefFailure(['const list = [1, 2]', 'let list = [3, 4]'], 'E1017:')
!   CheckDefFailure(['const two'], 'E1021:')
!   CheckDefFailure(['const &option'], 'E996:')
  
    let lines =<< trim END
!     const list = [1, 2, 3]
      list[0] = 4
      list->assert_equal([4, 2, 3])
!     const! other = [5, 6, 7]
      other->assert_equal([5, 6, 7])
  
      let varlist = [7, 8]
!     const! constlist = [1, varlist, 3]
      varlist[0] = 77
      # TODO: does not work yet
      # constlist[1][1] = 88
--- 193,213 ----
  enddef
  
  def Test_const()
!   CheckDefFailure(['final var = 234', 'var = 99'], 'E1018:')
!   CheckDefFailure(['final one = 234', 'let one = 99'], 'E1017:')
!   CheckDefFailure(['final list = [1, 2]', 'let list = [3, 4]'], 'E1017:')
!   CheckDefFailure(['final two'], 'E1125:')
!   CheckDefFailure(['final &option'], 'E996:')
  
    let lines =<< trim END
!     final list = [1, 2, 3]
      list[0] = 4
      list->assert_equal([4, 2, 3])
!     const other = [5, 6, 7]
      other->assert_equal([5, 6, 7])
  
      let varlist = [7, 8]
!     const constlist = [1, varlist, 3]
      varlist[0] = 77
      # TODO: does not work yet
      # constlist[1][1] = 88
***************
*** 216,222 ****
      constlist->assert_equal([1, [77, 88], 3])
  
      let vardict = #{five: 5, six: 6}
!     const! constdict = #{one: 1, two: vardict, three: 3}
      vardict['five'] = 55
      # TODO: does not work yet
      # constdict['two']['six'] = 66
--- 216,222 ----
      constlist->assert_equal([1, [77, 88], 3])
  
      let vardict = #{five: 5, six: 6}
!     const constdict = #{one: 1, two: vardict, three: 3}
      vardict['five'] = 55
      # TODO: does not work yet
      # constdict['two']['six'] = 66
***************
*** 229,263 ****
  
  def Test_const_bang()
    let lines =<< trim END
!       const! var = 234
        var = 99
    END
    CheckDefExecFailure(lines, 'E1018:', 2)
    CheckScriptFailure(['vim9script'] + lines, 'E46:', 3)
  
    lines =<< trim END
!       const! ll = [2, 3, 4]
        ll[0] = 99
    END
    CheckDefExecFailure(lines, 'E1119:', 2)
    CheckScriptFailure(['vim9script'] + lines, 'E741:', 3)
  
    lines =<< trim END
!       const! ll = [2, 3, 4]
        ll[3] = 99
    END
    CheckDefExecFailure(lines, 'E1118:', 2)
    CheckScriptFailure(['vim9script'] + lines, 'E684:', 3)
  
    lines =<< trim END
!       const! dd = #{one: 1, two: 2}
        dd["one"] = 99
    END
    CheckDefExecFailure(lines, 'E1121:', 2)
    CheckScriptFailure(['vim9script'] + lines, 'E741:', 3)
  
    lines =<< trim END
!       const! dd = #{one: 1, two: 2}
        dd["three"] = 99
    END
    CheckDefExecFailure(lines, 'E1120:')
--- 229,263 ----
  
  def Test_const_bang()
    let lines =<< trim END
!       const var = 234
        var = 99
    END
    CheckDefExecFailure(lines, 'E1018:', 2)
    CheckScriptFailure(['vim9script'] + lines, 'E46:', 3)
  
    lines =<< trim END
!       const ll = [2, 3, 4]
        ll[0] = 99
    END
    CheckDefExecFailure(lines, 'E1119:', 2)
    CheckScriptFailure(['vim9script'] + lines, 'E741:', 3)
  
    lines =<< trim END
!       const ll = [2, 3, 4]
        ll[3] = 99
    END
    CheckDefExecFailure(lines, 'E1118:', 2)
    CheckScriptFailure(['vim9script'] + lines, 'E684:', 3)
  
    lines =<< trim END
!       const dd = #{one: 1, two: 2}
        dd["one"] = 99
    END
    CheckDefExecFailure(lines, 'E1121:', 2)
    CheckScriptFailure(['vim9script'] + lines, 'E741:', 3)
  
    lines =<< trim END
!       const dd = #{one: 1, two: 2}
        dd["three"] = 99
    END
    CheckDefExecFailure(lines, 'E1120:')
***************
*** 2532,2537 ****
--- 2532,2543 ----
  def Test_let_declaration_fails()
    let lines =<< trim END
      vim9script
+     final var: string
+   END
+   CheckScriptFailure(lines, 'E1125:')
+ 
+   lines =<< trim END
+     vim9script
      const var: string
    END
    CheckScriptFailure(lines, 'E1021:')
*** ../vim-8.2.1743/src/version.c       2020-09-25 23:48:58.003938752 +0200
--- src/version.c       2020-09-26 14:38:34.834215914 +0200
***************
*** 752,753 ****
--- 752,755 ----
  {   /* Add new patch number below this line */
+ /**/
+     1744,
  /**/

-- 
Engineers understand that their appearance only bothers other people and
therefore it is not worth optimizing.
                                (Scott Adams - The Dilbert principle)

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\  an exciting new programming language -- http://www.Zimbu.org        ///
 \\\            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/202009261310.08QDA0uM743932%40masaka.moolenaar.net.

Raspunde prin e-mail lui