diff runtime/doc/vim9.txt @ 32670:695b50472e85

Fix line endings issue
author Christian Brabandt <cb@256bit.org>
date Mon, 26 Jun 2023 13:13:12 +0200
parents 448aef880252
children 2129fe5a2666
line wrap: on
line diff
--- a/runtime/doc/vim9.txt
+++ b/runtime/doc/vim9.txt
@@ -1,2251 +1,2251 @@
-*vim9.txt*	For Vim version 9.0.  Last change: 2023 Jun 10
-
-
-		  VIM REFERENCE MANUAL	  by Bram Moolenaar
-
-
-Vim9 script commands and expressions.			*Vim9* *vim9*
-
-Most expression help is in |eval.txt|.  This file is about the new syntax and
-features in Vim9 script.
-
-
-
-1.  What is Vim9 script?		|Vim9-script|
-2.  Differences				|vim9-differences|
-3.  New style functions			|fast-functions|
-4.  Types				|vim9-types|
-5.  Namespace, Import and Export	|vim9script|
-6.  Classes and interfaces		|vim9-classes|
-
-9.  Rationale				|vim9-rationale|
-
-==============================================================================
-
-1. What is Vim9 script?					*Vim9-script*
-
-Vim script has been growing over time, while preserving backwards
-compatibility.  That means bad choices from the past often can't be changed
-and compatibility with Vi restricts possible solutions.  Execution is quite
-slow, each line is parsed every time it is executed.
-
-The main goal of Vim9 script is to drastically improve performance.  This is
-accomplished by compiling commands into instructions that can be efficiently
-executed.  An increase in execution speed of 10 to 100 times can be expected.
-
-A secondary goal is to avoid Vim-specific constructs and get closer to
-commonly used programming languages, such as JavaScript, TypeScript and Java.
-
-The performance improvements can only be achieved by not being 100% backwards
-compatible.  For example, making function arguments available in the "a:"
-dictionary adds quite a lot of overhead.  In a Vim9 function this dictionary
-is not available.  Other differences are more subtle, such as how errors are
-handled.
-
-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
-- a command prefixed with the `vim9cmd` command modifier
-
-When using `:function` in a Vim9 script file the legacy syntax is used, with
-the highest |scriptversion|.  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.
-
-:vim9[cmd] {cmd}				*:vim9* *:vim9cmd* *E1164*
-		Evaluate and execute {cmd} using Vim9 script syntax and
-		semantics.  Useful when typing a command and in a legacy
-		script or function.
-
-:leg[acy] {cmd}					*:leg* *:legacy* *E1189* *E1234*
-		Evaluate and execute {cmd} using legacy script syntax and
-		semantics.  Only useful in a Vim9 script or a :def function.
-		Note that {cmd} cannot use local variables, since it is parsed
-		with legacy expression syntax.
-
-==============================================================================
-
-2. Differences from legacy Vim script			*vim9-differences*
-
-Overview ~
-							*E1146*
-Brief summary of the differences you will most often encounter when using Vim9
-script and `:def` functions; details are below:
-- Comments start with #, not ": >
-	echo "hello"   # comment
-- Using a backslash for line continuation is hardly ever needed: >
-	echo "hello "
-	     .. yourName
-	     .. ", how are you?"
-- White space is required in many places to improve readability.
-- Assign values without `:let` *E1126* , declare variables with `:var`: >
-	var count = 0
-	count += 3
-- Constants can be declared with `:final` and `:const`: >
-	final matches = []		  # add to the list later
-	const names = ['Betty', 'Peter']  # cannot be changed
-- `:final` cannot be used as an abbreviation of `:finally`.
-- Variables and functions are script-local by default.
-- Functions are declared with argument types and return type: >
-	def CallMe(count: number, message: string): bool
-- Call functions without `:call`: >
-	writefile(['done'], 'file.txt')
-- You cannot use old Ex commands:
-	`:Print`
-	`:append`
-	`:change`
-	`:d`  directly followed by 'd' or 'p'.
-	`:insert`
-	`:k`
-	`:mode`
-	`:open`
-	`:s`  with only flags
-	`:t`
-	`:xit`
-- Some commands, especially those used for flow control, cannot be shortened.
-  E.g., `:throw` cannot be written as `:th`.  *vim9-no-shorten*
-- You cannot use curly-braces names.
-- A range before a command must be prefixed with a colon: >
-	:%s/this/that
-- Executing a register with "@r" does not work, you can prepend a colon or use
-  `:exe`: >
-	:exe @a
-- Unless mentioned specifically, the highest |scriptversion| is used.
-- When defining an expression mapping, the expression will be evaluated in the
-  context of the script where it was defined.
-- When indexing a string the index is counted in characters, not bytes:
-  |vim9-string-index|
-- Some possibly unexpected differences: |vim9-gotchas|.
-
-
-Comments starting with # ~
-
-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
-to tell what the meaning is, since both a string and a comment can be followed
-by arbitrary text.  To avoid confusion only # comments are recognized.  This
-is the same as in shell scripts and Python programs.
-
-In Vi # is a command to list text with numbers.  In Vim9 script you can use
-`:number` for that. >
-	:101 number
-
-To improve readability there must be a space between a command and the #
-that starts a comment: >
-	var name = value # comment
-	var name = value# error!
-<							*E1170*
-Do not start a comment with #{, it looks like the legacy dictionary literal
-and produces an error where this might be confusing.  #{{ or #{{{ are OK,
-these can be used to start a fold.
-
-When starting to read a script file Vim doesn't know it is |Vim9| script until
-the `vim9script` command is found.  Until that point you would need to use
-legacy comments: >
-	" legacy comment
-	vim9script
-	# Vim9 comment
-
-That looks ugly, better put `vim9script` in the very first line: >
-	vim9script
-	# Vim9 comment
-
-In legacy Vim script # is also used for the alternate file name.  In Vim9
-script you need to use %% instead.  Instead of ## use %%% (stands for all
-arguments).
-
-
-Vim9 functions ~
-							*E1099*
-A function defined with `:def` is compiled.  Execution is many times faster,
-often 10 to 100 times.
-
-Many errors are already found when compiling, before the function is executed.
-The syntax is strict, to enforce code that is easy to read and understand.
-
-Compilation is done when any of these is encountered:
-- the first time the function is called
-- when the `:defcompile` command is encountered in the script after the
-  function was defined
-- `:disassemble` is used for the function.
-- a function that is compiled calls the function or uses it as a function
-  reference (so that the argument and return types can be checked)
-						*E1091* *E1191*
-If compilation fails it is not tried again on the next call, instead this
-error is given: "E1091: Function is not compiled: {name}".
-Compilation will fail when encountering a user command that has not been
-created yet.  In this case you can call `execute()` to invoke it at runtime. >
-	def MyFunc()
-	  execute('DefinedLater')
-	enddef
-
-`:def` has no options like `:function` does: "range", "abort", "dict" or
-"closure".  A `:def` function always aborts on an error (unless `:silent!` was
-used for the command or the error was caught a `:try` block), does not get a
-range passed, cannot be a "dict" function, and can always be a closure.
-						*vim9-no-dict-function*
-You can use a Vim9 Class (|Vim9-class|) instead of a "dict function".
-You can also pass the dictionary explicitly: >
-	def DictFunc(self: dict<any>, arg: string)
-	   echo self[arg]
-	enddef
-	var ad = {item: 'value', func: DictFunc}
-	ad.func(ad, 'item')
-
-You can call a legacy dict function though: >
-	func Legacy() dict
-	  echo self.value
-	endfunc
-	def CallLegacy()
-	  var d = {func: Legacy, value: 'text'}
-	  d.func()
-	enddef
-<						*E1096* *E1174* *E1175*
-The argument types and return type need to be specified.  The "any" type can
-be used, type checking will then be done at runtime, like with legacy
-functions.
-							*E1106*
-Arguments are accessed by name, without "a:", just like any other language.
-There is no "a:" dictionary or "a:000" list.
-			*vim9-variable-arguments* *E1055* *E1160* *E1180*
-Variable arguments are defined as the last argument, with a name and have a
-list type, similar to TypeScript.  For example, a list of numbers: >
-	def MyFunc(...itemlist: list<number>)
-	   for item in itemlist
-	     ...
-
-When a function argument is optional (it has a default value) passing `v:none`
-as the argument results in using the default value.  This is useful when you
-want to specify a value for an argument that comes after an argument that
-should use its default value.  Example: >
-	def MyFunc(one = 'one', last = 'last')
-	  ...
-	enddef
-	MyFunc(v:none, 'LAST')  # first argument uses default value 'one'
-<
-					*vim9-ignored-argument* *E1181*
-The argument "_" (an underscore) can be used to ignore the argument.  This is
-most useful in callbacks where you don't need it, but do need to give an
-argument to match the call.  E.g. when using map() two arguments are passed,
-the key and the value, to ignore the key: >
-	map(numberList, (_, v) => v * 2)
-There is no error for using the "_" argument multiple times.  No type needs to
-be given.
-
-
-Functions and variables are script-local by default ~
-							*vim9-scopes*
-When using `:function` or `:def` to specify a new function at the script level
-in a Vim9 script, the function is local to the script.  Like prefixing "s:" in
-legacy script.  To define a global function or variable the "g:" prefix must
-be used.  For functions in a script that is to be imported and in an autoload
-script "export" needs to be used for those to be used elsewhere. >
-	def ThisFunction()          # script-local
-	def g:ThatFunction()        # global
-	export def Function()       # for import and import autoload
-<						*E1058* *E1075*
-When using `:function` or `:def` to specify a nested function inside a `:def`
-function and no namespace was given, this nested function is local to the code
-block it is defined in.  It cannot be used in `function()` with a string
-argument, pass the function reference itself: >
-	def Outer()
-	  def Inner()
-	    echo 'inner'
-	  enddef
-	  var Fok = function(Inner)     # OK
-	  var Fbad = function('Inner')  # does not work
-
-Detail: this is because "Inner" will actually become a function reference to a
-function with a generated name.
-
-It is not possible to define a script-local function in a function.  You can
-define a local function and assign it to a script-local Funcref (it must have
-been declared at the script level).  It is possible to define a global
-function by using the "g:" prefix.
-
-When referring to a function and no "s:" or "g:" prefix is used, Vim will
-search for the function:
-- in the function scope, in block scopes
-- in the script scope
-
-Imported functions are found with the prefix from the `:import` command.
-
-Since a script-local function reference can be used without "s:" the name must
-start with an upper case letter even when using the "s:" prefix.  In legacy
-script "s:funcref" could be used, because it could not be referred to with
-"funcref".  In Vim9 script it can, therefore "s:Funcref" must be used to avoid
-that the name interferes with builtin functions.
-						*vim9-s-namespace* *E1268*
-The use of the "s:" prefix is not supported at the Vim9 script level.  All
-functions and variables without a prefix are script-local.
-
-In :def functions the use of "s:" depends on the script: Script-local
-variables and functions in a legacy script do use "s:", while in a Vim9 script
-they do not use "s:".  This matches what you see in the rest of the file.
-
-In legacy functions the use of "s:" for script items is required, as before.
-No matter if the script is Vim9 or legacy.
-
-In all cases the function must be defined before used.  That is when it is
-called, when `:defcompile` causes it to be compiled, or when code that calls
-it is being compiled (to figure out the return type).
-
-The result is that functions and variables without a namespace can usually be
-found in the script, either defined there or imported.  Global functions and
-variables could be defined anywhere (good luck finding out where!  You can
-often see where it was last set using |:verbose|).
-							*E1102*
-Global functions can still be defined and deleted at nearly any time.  In
-Vim9 script script-local functions are defined once when the script is sourced
-and cannot be deleted or replaced by itself (it can be by reloading the
-script).
-
-When compiling a function and a function call is encountered for a function
-that is not (yet) defined, the |FuncUndefined| autocommand is not triggered.
-You can use an autoload function if needed, or call a legacy function and have
-|FuncUndefined| triggered there.
-
-
-Reloading a Vim9 script clears functions and variables by default ~
-						*vim9-reload* *E1149* *E1150*
-When loading a legacy Vim script a second time nothing is removed, the
-commands will replace existing variables and functions, create new ones, and
-leave removed things hanging around.
-
-When loading a Vim9 script a second time all existing script-local functions
-and variables are deleted, thus you start with a clean slate.  This is useful
-if you are developing a plugin and want to try a new version.  If you renamed
-something you don't have to worry about the old name still hanging around.
-
-If you do want to keep items, use: >
-	vim9script noclear
-
-You want to use this in scripts that use a `finish` command to bail out at
-some point when loaded again.  E.g. when a buffer local option is set to a
-function, the function does not need to be defined more than once: >
-	vim9script noclear
-	setlocal completefunc=SomeFunc
-	if exists('*SomeFunc')
-	  finish
-	endif
-	def SomeFunc()
-	....
-
-
-Variable declarations with :var, :final and :const ~
-				*vim9-declaration* *:var* *E1079*
-				*E1017* *E1020* *E1054* *E1087* *E1124*
-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
-	   inner = 0
-	endif
-	echo inner
-
-Although this is shorter and faster for simple values: >
-	var inner = 0
-	if cond
-	   inner = 5
-	endif
-	echo inner
-<							*E1025* *E1128*
-To intentionally hide a variable from code that follows, a block can be
-used: >
-	{
-	   var temp = 'temp'
-	   ...
-	}
-	echo temp  # Error!
-
-This is especially useful in a user command: >
-	command -range Rename {
-		 var save = @a
-		 @a = 'some expression'
-		 echo 'do something with ' .. @a
-		 @a = save
-	    }
-
-And with autocommands: >
-   au BufWritePre *.go {
-		 var save = winsaveview()
-		 silent! exe ':%! some formatting command'
-		 winrestview(save)
-	   }
-
-Although using a :def function probably works better.
-
-				*E1022* *E1103* *E1130* *E1131* *E1133*
-				*E1134*
-Declaring a variable with a type but without an initializer will initialize to
-false (for bool), empty (for string, list, dict, etc.) or zero (for number,
-any, etc.).  This matters especially when using the "any" type, the value will
-default to the number zero.  For example, when declaring a list, items can be
-added: >
-	var myList: list<number>
-	myList->add(7)
-
-Initializing a variable to a null value, e.g. `null_list`, differs from not
-initializing the variable.  This throws an error: >
-	var myList = null_list
-	myList->add(7)  # E1130: Cannot add to null list
-
-<						*E1016* *E1052* *E1066*
-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.  Those can also be deleted
-with `:unlet`.
-							*E1065*
-You cannot use `:va` to declare a variable, it must be written with the full
-name `:var`.  Just to make sure it is easy to read.
-							*E1178*
-`:lockvar` does not work on local variables.  Use `:const` and `:final`
-instead.
-
-The `exists()` and `exists_compiled()` functions do not work on local variables
-or arguments.
-				*E1006* *E1041* *E1167* *E1168* *E1213*
-Variables, functions and function arguments cannot shadow previously defined
-or imported variables and functions in the same script file.
-Variables may shadow Ex commands, rename the variable if needed.
-
-Global variables must be prefixed with "g:", also at the script level. >
-	vim9script
-	var script_local = 'text'
-	g:global = 'value'
-	var Funcref = g:ThatFunction
-
-Global functions must be prefixed with "g:": >
-	vim9script
-	def g:GlobalFunc(): string
-	  return 'text'
-	enddef
-	echo g:GlobalFunc()
-The "g:" prefix is not needed for auto-load functions.
-
-					*vim9-function-defined-later*
-Although global functions can be called without the "g:" prefix, they must
-exist when compiled.  By adding the "g:" prefix the function can be defined
-later.  Example: >
-	def CallPluginFunc()
-	  if exists('g:loaded_plugin')
-	    g:PluginFunc()
-	  endif
-	enddef
-
-If you do it like this, you get an error at compile time that "PluginFunc"
-does not exist, even when "g:loaded_plugin" does not exist: >
-	def CallPluginFunc()
-	  if exists('g:loaded_plugin')
-	    PluginFunc()   # Error - function not found
-	  endif
-	enddef
-
-You can use exists_compiled() to avoid the error, but then the function would
-not be called, even when "g:loaded_plugin" is defined later: >
-	def CallPluginFunc()
-	  if exists_compiled('g:loaded_plugin')
-	    PluginFunc()   # Function may never be called
-	  endif
-	enddef
-
-Since `&opt = value` is now assigning a value to option "opt", ":&" cannot be
-used to repeat a `:substitute` command.
-							*vim9-unpack-ignore*
-For an unpack assignment the underscore can be used to ignore a list item,
-similar to how a function argument can be ignored: >
-	[a, _, c] = theList
-To ignore any remaining items: >
-	[a, b; _] = longList
-<							*E1163* *E1080*
-Declaring more than one variable at a time, using the unpack notation, is
-possible.  Each variable can have a type or infer it from the value: >
-	var [v1: number, v2] = GetValues()
-Use this only when there is a list with values, declaring one variable per
-line is much easier to read and change later.
-
-
-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.
-							*E1021* *E1307*
-`: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!
-	myList->add(3)		# Error!
-<							*:final* *E1125*
-`: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
-	myList->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"
-
-
-Omitting :call and :eval ~
-							*E1190*
-Functions can be called without `:call`: >
-	writefile(lines, 'file')
-Using `:call` is still possible, but this is discouraged.
-
-A method call without `eval` is possible, so long as the start is an
-identifier or can't be an Ex command.  For a function either "(" or "->" must
-be following, without a line break.  Examples: >
-	myList->add(123)
-	g:myList->add(123)
-	[1, 2, 3]->Process()
-	{a: 1, b: 2}->Process()
-	"foobar"->Process()
-	("foobar")->Process()
-	'foobar'->Process()
-	('foobar')->Process()
-
-In the rare case there is ambiguity between a function name and an Ex command,
-prepend ":" to make clear you want to use the Ex command.  For example, there
-is both the `:substitute` command and the `substitute()` function.  When the
-line starts with `substitute(` this will use the function. Prepend a colon to
-use the command instead: >
-	:substitute(pattern (replacement (
-
-If the expression starts with "!" this is interpreted as a shell command, not
-negation of a condition.  Thus this is a shell command: >
-	!shellCommand->something
-Put the expression in parentheses to use the "!" for negation: >
-	(!expression)->Method()
-
-Note that while variables need to be defined before they can be used,
-functions can be called before being defined.  This is required to allow
-for cyclic dependencies between functions.  It is slightly less efficient,
-since the function has to be looked up by name.  And a typo in the function
-name will only be found when the function is called.
-
-
-Omitting function() ~
-
-A user defined function can be used as a function reference in an expression
-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 (including void).  The function can be
-defined later if the argument is in quotes.
-
-
-Lambda using => instead of -> ~
-							*vim9-lambda*
-In legacy script there can be confusion between using "->" for a method call
-and for a lambda.  Also, when a "{" is found the parser needs to figure out if
-it is the start of a lambda or a dictionary, which is now more complicated
-because of the use of argument types.
-
-To avoid these problems Vim9 script uses a different syntax for a lambda,
-which is similar to JavaScript: >
-	var Lambda = (arg) => expression
-	var Lambda = (arg): type => expression
-<							*E1157*
-No line break is allowed in the arguments of a lambda up to and including the
-"=>" (so that Vim can tell the difference between an expression in parentheses
-and lambda arguments).  This is OK: >
-	filter(list, (k, v) =>
-			v > 0)
-This does not work: >
-	filter(list, (k, v)
-			=> v > 0)
-This also does not work: >
-	filter(list, (k,
-			v) => v > 0)
-But you can use a backslash to concatenate the lines before parsing: >
-	filter(list, (k,
-		\	v)
-		\	=> v > 0)
-<					*vim9-lambda-arguments* *E1172*
-In legacy script a lambda could be called with any number of extra arguments,
-there was no way to warn for not using them.  In Vim9 script the number of
-arguments must match.  If you do want to accept any arguments, or any further
-arguments, use "..._", which makes the function accept
-|vim9-variable-arguments|.  Example: >
-	var Callback = (..._) => 'anything'
-	echo Callback(1, 2, 3)  # displays "anything"
-
-<						*inline-function* *E1171*
-Additionally, a lambda can contain statements in {}: >
-	var Lambda = (arg) => {
-		g:was_called = 'yes'
-		return expression
-	    }
-This can be useful for a timer, for example: >
-	var count = 0
-	var timer = timer_start(500, (_) => {
-		 count += 1
-		 echom 'Handler called ' .. count
-	     }, {repeat: 3})
-
-The ending "}" must be at the start of a line.  It can be followed by other
-characters, e.g.: >
-	var d = mapnew(dict, (k, v): string => {
-	     return 'value'
-	   })
-No command can follow the "{", only a comment can be used there.
-
-						*command-block* *E1026*
-The block can also be used for defining a user command.  Inside the block Vim9
-syntax will be used.
-
-If the statements include a dictionary, its closing bracket must not be
-written at the start of a line.  Otherwise, it would be parsed as the end of
-the block.  This does not work: >
-	command NewCommand {
-	     g:mydict = {
-	       'key': 'value',
-	       }  # ERROR: will be recognized as the end of the block
-	   }
-Put the '}' after the last item to avoid this: >
-	command NewCommand {
-	     g:mydict = {
-	       'key': 'value' }
-	   }
-
-Rationale: The "}" cannot be after a command because it would require parsing
-the commands to find it.  For consistency with that no command can follow the
-"{".  Unfortunately this means using "() => {  command  }" does not work, line
-breaks are always required.
-
-							*vim9-curly*
-To avoid the "{" of a dictionary literal to be recognized as a statement block
-wrap it in parentheses: >
-	var Lambda = (arg) => ({key: 42})
-
-Also when confused with the start of a command block: >
-	({
-	    key: value
-	 })->method()
-
-
-Automatic line continuation ~
-					*vim9-line-continuation* *E1097*
-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 (see
-|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,
-		}
-With a 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
-
-For commands that have an argument that is a list of commands, the | character
-at the start of the line indicates line continuation: >
-	autocmd BufNewFile *.match if condition
-		|   echo 'match'
-		| endif
-
-Note that this means that in heredoc the first line cannot start with a bar: >
-	var lines =<< trim END
-	   | this doesn't work
-	END
-Either use an empty line at the start or do not use heredoc.  Or temporarily
-add the "C" flag to 'cpoptions': >
-	set cpo+=C
-	var lines =<< trim END
-	   | this works
-	END
-	set cpo-=C
-If the heredoc is inside a function 'cpoptions' must be set before :def and
-restored after the :enddef.
-
-In places where line continuation with a backslash is still needed, such as
-splitting up a long Ex command, comments can start with '#\ ': >
-	syn region Text
-	      \ start='foo'
-	      #\ comment
-	      \ end='bar'
-Like with legacy script '"\ ' is used.  This is also needed when line
-continuation is used without a backslash and a line starts with a bar: >
-	au CursorHold * echom 'BEFORE bar'
-	      #\ some comment
-	      | echom 'AFTER bar'
-<
-							*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 example 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
-
-After the range an Ex command must follow.  Without the colon you can call a
-function without `:call`, but after a range you do need it: >
-	MyFunc()
-	:% call MyFunc()
-
-Note that the colon is not required for the |+cmd| argument: >
-	edit +6 fname
-
-It is also possible to split a function header over multiple lines, in between
-arguments: >
-	def MyFunc(
-		text: string,
-		separator = '-'
-		): string
-
-Since a continuation line cannot be easily recognized the parsing of commands
-has been made stricter.  E.g., because of the error in the first line, the
-second line is seen as a separate command: >
-	popup_create(some invalid expression, {
-	   exit_cb: Func})
-Now "exit_cb: Func})" is actually a valid command: save any changes to the
-file "_cb: Func})" and exit.  To avoid this kind of mistake in Vim9 script
-there must be white space between most command names and the argument.
-*E1144*
-
-However, the argument of a command that is a command won't be recognized.  For
-example, after "windo echo expr" a line break inside "expr" will not be seen.
-
-
-Notes:
-- "enddef" cannot be used at the start of a continuation line, it ends the
-  current function.
-- No line break is allowed in the LHS of an assignment.  Specifically when
-  unpacking a list |:let-unpack|. This is OK: >
-	[var1, var2] =
-		Func()
-<  This does not work: >
-	[var1,
-	    var2] =
-		Func()
-- No line break is allowed in between arguments of an `:echo`, `:execute` and
-  similar commands.  This is OK: >
-	echo [1,
-		2] [3,
-			4]
-<  This does not work: >
-	echo [1, 2]
-		[3, 4]
-- In some cases it is difficult for Vim to parse a command, especially when
-  commands are used as an argument to another command, such as `:windo`.  In
-  those cases the line continuation with a backslash has to be used.
-
-
-White space ~
-			*E1004* *E1068* *E1069* *E1074* *E1127* *E1202*
-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.
-
-White space is required in a sublist (list slice) around the ":", except at
-the start and end: >
-	otherlist = mylist[v : count]	# v:count has a different meaning
-	otherlist = mylist[:]		# make a copy of the List
-	otherlist = mylist[v :]
-	otherlist = mylist[: v]
-
-White space is not allowed:
-- Between a function name and the "(": >
-	Func (arg)	   # Error!
-	Func
-	     \ (arg)	   # Error!
-	Func
-	      (arg)	   # Error!
-	Func(arg)	   # OK
-	Func(
-	      arg)	   # OK
-	Func(
-	      arg	   # OK
-	      )
-<							*E1205*
-White space is not allowed in a `:set` command between the option name and a
-following "&", "!", "<", "=", "+=", "-=" or "^=".
-
-
-No curly braces expansion ~
-
-|curly-braces-names| cannot be used.
-
-
-Command modifiers are not ignored ~
-								*E1176*
-Using a command modifier for a command that does not use it gives an error.
-								*E1082*
-Also, using a command modifier without a following command is now an error.
-
-
-Dictionary literals ~
-						*vim9-literal-dict* *E1014*
-Traditionally Vim has supported dictionary literals with a {} syntax: >
-	let dict = {'key': value}
-
-Later it became clear that using a simple text key is very common, thus
-literal dictionaries were introduced in a backwards compatible way: >
-	let dict = #{key: value}
-
-However, this #{} syntax is unlike any existing language.  As it turns out
-that using a literal key is much more common than using an expression, and
-considering that JavaScript uses this syntax, using the {} form for dictionary
-literals is considered a much more useful syntax.  In Vim9 script the {} form
-uses literal keys: >
-	var dict = {key: value}
-
-This works for alphanumeric characters, underscore and dash.  If you want to
-use another character, use a single or double quoted string: >
-	var dict = {'key with space': value}
-	var dict = {"key\twith\ttabs": value}
-	var dict = {'': value}			# empty key
-<							*E1139*
-In case the key needs to be an expression, square brackets can be used, just
-like in JavaScript: >
-	var dict = {["key" .. nr]: value}
-
-The key type can be string, number, bool or float.  Other types result in an
-error.  Without using [] the value is used as a string, keeping leading zeros.
-An expression given with [] is evaluated and then converted to a string.
-Leading zeros will then be dropped: >
-	var dict = {000123: 'without', [000456]: 'with'}
-	echo dict
-	{'456': 'with', '000123': 'without'}
-A float only works inside [] because the dot is not accepted otherwise: >
-	var dict = {[00.013]: 'float'}
-	echo dict
-	{'0.013': 'float'}
-
-
-No :xit, :t, :k, :append, :change or :insert ~
-							*E1100*
-These commands are too easily confused with local variable names.
-Instead of `:x` or `:xit` you can use `:exit`.
-Instead of `:t` you can use `:copy`.
-Instead of `:k` you can use `:mark`.
-
-
-Comparators ~
-
-The 'ignorecase' option is not used for comparators that use strings.
-Thus "=~" works like "=~#".
-
-"is" and "isnot" (|expr-is| and |expr-isnot|) when used on strings now return
-false.  In legacy script they just compare the strings, in |Vim9| script they
-check identity, and strings are copied when used, thus two strings are never
-the same (this might change someday if strings are not copied but reference
-counted).
-
-
-Abort after error ~
-
-In legacy script, when an error is encountered, Vim continues to execute
-following lines.  This can lead to a long sequence of errors and need to type
-CTRL-C to stop it.  In Vim9 script execution of commands stops at the first
-error.  Example: >
-	vim9script
-	var x = does-not-exist
-	echo 'not executed'
-
-
-For loop ~
-							*E1254*
-The loop variable must not be declared yet: >
-	var i = 1
-	for i in [1, 2, 3]   # Error!
-
-It is possible to use a global variable though: >
-	g:i = 1
-	for g:i in [1, 2, 3]
-	  echo g:i
-	endfor
-
-Legacy Vim script has some tricks to make a for loop over a list handle
-deleting items at the current or previous item.  In Vim9 script it just uses
-the index, if items are deleted then items in the list will be skipped.
-Example legacy script: >
-	let l = [1, 2, 3, 4]
-	for i in l
-	   echo i
-	   call remove(l, index(l, i))
-	endfor
-Would echo:
-	1
-	2
-	3
-	4
-In compiled Vim9 script you get:
-	1
-	3
-Generally, you should not change the list that is iterated over.  Make a copy
-first if needed.
-When looping over a list of lists, the nested lists can be changed.  The loop
-variable is "final", it cannot be changed but what its value can be changed.
-							*E1306*
-The depth of loops, :for and :while loops added together, cannot exceed 10.
-
-
-Conditions and expressions ~
-						*vim9-boolean*
-Conditions and expressions are mostly working like they do in other languages.
-Some values are different from legacy Vim script:
-	value		legacy Vim script	Vim9 script ~
-	0		falsy			falsy
-	1		truthy			truthy
-	99		truthy			Error!
-	"0"		falsy			Error!
-	"99"		truthy			Error!
-	"text"		falsy			Error!
-
-For the "??" operator and when using "!" then there is no error, every value
-is either falsy or truthy.  This is mostly like JavaScript, except that an
-empty list and dict is falsy:
-
-	type		truthy when ~
-	bool		true, v:true or 1
-	number		non-zero
-	float		non-zero
-	string		non-empty
-	blob		non-empty
-	list		non-empty (different from JavaScript)
-	dictionary	non-empty (different from JavaScript)
-	func		when there is a function name
-	special		true or v:true
-	job		when not NULL
-	channel		when not NULL
-	class		when not NULL
-	object		when not NULL (TODO: when isTrue() returns true)
-
-The boolean operators "||" and "&&" expect the values to be boolean, zero or
-one: >
-	1 || false   == true
-	0 || 1       == true
-	0 || false   == false
-	1 && true    == true
-	0 && 1       == false
-	8 || 0	     Error!
-	'yes' && 0   Error!
-	[] || 99     Error!
-
-When using "!" for inverting, there is no error for using any type and the
-result is a boolean.  "!!" can be used to turn any value into boolean: >
-	!'yes'			== false
-	!![]			== false
-	!![1, 2, 3]		== true
-
-When using "`.."` for string concatenation arguments of simple types are
-always converted to string: >
-	'hello ' .. 123  == 'hello 123'
-	'hello ' .. v:true  == 'hello true'
-
-Simple types are Number, Float, Special and Bool.  For other types |string()|
-should be used.
-			*false* *true* *null* *null_blob* *null_channel*
-			*null_dict* *null_function* *null_job* *null_list*
-			*null_partial* *null_string* *E1034*
-In Vim9 script one can use the following predefined values: >
-	true
-	false
-	null
-	null_blob
-	null_channel
-	null_dict
-	null_function
-	null_job
-	null_list
-	null_partial
-	null_string
-`true` is the same as `v:true`, `false` the same as `v:false`, `null` the same
-as `v:null`.
-
-While `null` has the type "special", the other "null_" values have the type
-indicated by their name.  Quite often a null value is handled the same as an
-empty value, but not always.  The values can be useful to clear a script-local
-variable, since they cannot be deleted with `:unlet`.  E.g.: >
-	var theJob = job_start(...)
-	# let the job do its work
-	theJob = null_job
-
-The values can also be useful as the default value for an argument: >
-	def MyFunc(b: blob = null_blob)
-	   if b == null_blob
-	      # b argument was not given
-
-It is possible to compare `null`  with any value, this will not give a type
-error.  However, comparing `null` with a number, float or bool will always
-result in `false`.  This is different from legacy script, where comparing
-`null` with zero or `false` would return `true`.
-							*vim9-false-true*
-When converting a boolean to a string `false` and `true` are used, not
-`v:false` and `v:true` like in legacy script.  `v:none` has no `none`
-replacement, it has no equivalent in other languages.
-							*vim9-string-index*
-Indexing a string with [idx] or taking a slice with [idx : idx] uses character
-indexes instead of byte indexes.  Composing characters are included.
-Example: >
-	echo 'bár'[1]
-In legacy script this results in the character 0xc3 (an illegal byte), in Vim9
-script this results in the string 'á'.
-A negative index is counting from the end, "[-1]" is the last character.
-To exclude the last character use |slice()|.
-To count composing characters separately use |strcharpart()|.
-If the index is out of range then an empty string results.
-
-In legacy script "++var" and "--var" would be silently accepted and have no
-effect.  This is an error in Vim9 script.
-
-Numbers starting with zero are not considered to be octal, only numbers
-starting with "0o" are octal: "0o744". |scriptversion-4|
-
-
-What to watch out for ~
-							*vim9-gotchas*
-Vim9 was designed to be closer to often used programming languages, but at the
-same time tries to support the legacy Vim commands.  Some compromises had to
-be made.  Here is a summary of what might be unexpected.
-
-Ex command ranges need to be prefixed with a colon. >
-	->		  legacy Vim: shifts the previous line to the right
-	->func()	  Vim9: method call in a continuation line
-	:->		  Vim9: shifts the previous line to the right
-
-	%s/a/b		  legacy Vim: substitute on all lines
-	x = alongname
-	     % another	  Vim9: modulo operator in a continuation line
-	:%s/a/b		  Vim9: substitute on all lines
-	't		  legacy Vim: jump to mark t
-	'text'->func()	  Vim9: method call
-	:'t		  Vim9: jump to mark t
-
-Some Ex commands can be confused with assignments in Vim9 script: >
-	g:name = value    # assignment
-	:g:pattern:cmd	  # :global command
-
-To avoid confusion between a `:global` or `:substitute` command and an
-expression or assignment, a few separators cannot be used when these commands
-are abbreviated to a single character: ':', '-' and '.'. >
-	g:pattern:cmd	  # invalid command - ERROR
-	s:pattern:repl	  # invalid command - ERROR
-	g-pattern-cmd	  # invalid command - ERROR
-	s-pattern-repl	  # invalid command - ERROR
-	g.pattern.cmd	  # invalid command - ERROR
-	s.pattern.repl	  # invalid command - ERROR
-
-Also, there cannot be a space between the command and the separator: >
-	g /pattern/cmd	  # invalid command - ERROR
-	s /pattern/repl	  # invalid command - ERROR
-
-Functions defined with `:def` compile the whole function.  Legacy functions
-can bail out, and the following lines are not parsed: >
-	func Maybe()
-	  if !has('feature')
-	    return
-	  endif
-	  use-feature
-	endfunc
-Vim9 functions are compiled as a whole: >
-	def Maybe()
-	  if !has('feature')
-	    return
-	  endif
-	  use-feature  # May give a compilation error
-	enddef
-For a workaround, split it in two functions: >
-	func Maybe()
-	  if has('feature')
-	    call MaybeInner()
-	  endif
-	endfunc
-	if has('feature')
-	  def MaybeInner()
-	    use-feature
-	  enddef
-	endif
-Or put the unsupported code inside an `if` with a constant expression that
-evaluates to false: >
-	def Maybe()
-	  if has('feature')
-	    use-feature
-	  endif
-	enddef
-The `exists_compiled()` function can also be used for this.
-							*vim9-user-command*
-Another side effect of compiling a function is that the presence of a user
-command is checked at compile time.  If the user command is defined later an
-error will result.  This works: >
-	command -nargs=1 MyCommand echom <q-args>
-	def Works()
-	  MyCommand 123
-	enddef
-This will give an error for "MyCommand" not being defined: >
-	def Works()
-	  command -nargs=1 MyCommand echom <q-args>
-	  MyCommand 123
-	enddef
-A workaround is to invoke the command indirectly with `:execute`: >
-	def Works()
-	  command -nargs=1 MyCommand echom <q-args>
-	  execute 'MyCommand 123'
-	enddef
-
-Note that for unrecognized commands there is no check for "|" and a following
-command.  This will give an error for missing `endif`: >
-	def Maybe()
-	  if has('feature') | use-feature | endif
-	enddef
-
-Other differences ~
-
-Patterns are used like 'magic' is set, unless explicitly overruled.
-The 'edcompatible' option value is not used.
-The 'gdefault' option value is not used.
-
-You may also find this wiki useful.  It was written by an early adopter of
-Vim9 script: https://github.com/lacygoill/wiki/blob/master/vim/vim9.md
-
-							*:++* *:--*
-The ++ and -- commands have been added.  They are very similar to adding or
-subtracting one: >
-		++var
-		var += 1
-		--var
-		var -= 1
-
-Using ++var or --var in an expression is not supported yet.
-
-==============================================================================
-
-3. New style functions					*fast-functions*
-
-							*:def* *E1028*
-:def[!] {name}([arguments])[: {return-type}]
-			Define a new function by the name {name}.  The body of
-			the function follows in the next lines, until the
-			matching `:enddef`. *E1073*
-							*E1011*
-			The {name} must be less than 100 bytes long.
-					*E1003* *E1027* *E1056* *E1059*
-			The type of value used with `:return` must match
-			{return-type}.  When {return-type} is omitted or is
-			"void" the function is not expected to return
-			anything.
-							*E1077* *E1123*
-			{arguments} is a sequence of zero or more argument
-			declarations.  There are three forms:
-				{name}: {type}
-				{name} = {value}
-				{name}: {type} = {value}
-			The first form is a mandatory argument, the caller
-			must always provide them.
-			The second and third form are optional arguments.
-			When the caller omits an argument the {value} is used.
-
-			The function will be compiled into instructions when
-			called, or when `:disassemble` or `:defcompile` is
-			used.  Syntax and type errors will be produced at that
-			time.
-
-			It is possible to nest `:def` inside another `:def` or
-			`:function` up to about 50 levels deep.
-							*E1117*
-			[!] 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* *E1057* *E1152* *E1173*
-:enddef			End of a function defined with `:def`. It should be on
-			a line by its own.
-
-You may also find this wiki useful.  It was written by an early adopter of
-Vim9 script: https://github.com/lacygoill/wiki/blob/master/vim/vim9.md
-
-If the script the function is defined in is Vim9 script, then script-local
-variables can be accessed without the "s:" prefix.  They must be defined
-before the function is compiled.  If the script the function is defined in is
-legacy script, then script-local variables must be accessed with the "s:"
-prefix if they do not exist at the time of compiling.
-							*E1269*
-Script-local variables in a |Vim9| script must be declared at the script
-level.  They cannot be created in a function, also not in a legacy function.
-
-						*:defc* *:defcompile*
-:defc[ompile]		Compile functions defined in the current script that
-			were not compiled yet.
-			This will report any errors found during compilation.
-			This excludes functions defined inside a class.
-
-:defc[ompile] {func}
-:defc[ompile] debug {func}
-:defc[ompile] profile {func}
-			Compile function {func}, if needed.  Use "debug" and
-			"profile" to specify the compilation mode.
-			This will report any errors found during compilation.
-			{func} call also be "ClassName.functionName" to
-			compile a function or method in a class.
-			{func} call also be "ClassName" to compile all
-			functions and methods in a class.
-
-						*:disa* *:disassemble*
-:disa[ssemble] {func}	Show the instructions generated for {func}.
-			This is for debugging and testing. *E1061*
-			Note that for command line completion of {func} you
-			can prepend "s:" to find script-local functions.
-
-:disa[ssemble] profile {func}
-			Like `:disassemble` but with the instructions used for
-			profiling.
-
-:disa[ssemble] debug {func}
-			Like `:disassemble` but with the instructions used for
-			debugging.
-
-Limitations ~
-
-Local variables will not be visible to string evaluation.  For example: >
-	def MapList(): 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 MapList(): list<string>
-	  var list = ['aa', 'bb', 'cc', 'dd']
-	  return range(1, 2)->map((_, v) => list[v])
-	enddef
-
-For commands that are not compiled, such as `:edit`, backtick expansion can be
-used and it can use the local scope.  Example: >
-	def Replace()
-	  var fname = 'blah.txt'
-	  edit `=fname`
-	enddef
-
-Closures defined in a loop will share the same context.  For example: >
-	var flist: list<func>
-	for i in range(5)
-	  var inloop = i
-	  flist[i] = () => inloop
-	endfor
-	echo range(5)->map((i, _) => flist[i]())
-	# Result: [4, 4, 4, 4, 4]
-<							*E1271*
-A closure must be compiled in the context that it is defined in, so that
-variables in that context can be found.  This mostly happens correctly, except
-when a function is marked for debugging with `:breakadd` after it was compiled.
-Make sure to define the breakpoint before compiling the outer function.
-
-The "inloop" variable will exist only once, all closures put in the list refer
-to the same instance, which in the end will have the value 4.  This is
-efficient, also when looping many times.  If you do want a separate context
-for each closure, call a function to define it: >
-	def GetClosure(i: number): func
-	  var infunc = i
-	  return () => infunc
-	enddef
-
-	var flist: list<func>
-	for i in range(5)
-	  flist[i] = GetClosure(i)
-	endfor
-	echo range(5)->map((i, _) => flist[i]())
-	# Result: [0, 1, 2, 3, 4]
-
-In some situations, especially when calling a Vim9 closure from legacy
-context, the evaluation will fail.  *E1248*
-
-Note that at the script level the loop variable will be invalid after the
-loop, also when used in a closure that is called later, e.g. with a timer.
-This will generate error |E1302|: >
-	for n in range(4)
-	    timer_start(500 * n, (_) => {
-	          echowin n
-	       })
-	endfor
-
-You need to use a block and define a variable there, and use that one in the
-closure: >
-	for n in range(4)
-	{
-	   var nr = n
-	   timer_start(500 * n, (_) => {
-	          echowin nr
-	      })
-	}
-	endfor
-
-Using `:echowindow` is useful in a timer, the messages go into a popup and will
-not interfere with what the user is doing when it triggers.
-
-
-Converting a function from legacy to Vim9 ~
-					*convert_legacy_function_to_vim9*
-These are the most changes that need to be made to convert a legacy function
-to a Vim9 function:
-
-- Change `func` or `function` to `def`.
-- Change `endfunc` or `endfunction` to `enddef`.
-- Add types to the function arguments.
-- If the function returns something, add the return type.
-- Change comments to start with # instead of ".
-
-  For example, a legacy function: >
-	func MyFunc(text)
-	  " function body
-	endfunc
-<  Becomes: >
-	def MyFunc(text: string): number
-	  # function body
-	enddef
-
-- Remove "a:" used for arguments. E.g.: >
-	return len(a:text)
-<  Becomes: >
-	return len(text)
-
-- Change `let` used to declare a variable to `var`.
-- Remove `let` used to assign a value to a variable.  This is for local
-  variables already declared and b: w: g: and t: variables.
-
-  For example, legacy function: >
-	  let lnum = 1
-	  let lnum += 3
-	  let b:result = 42
-<  Becomes: >
-	  var lnum = 1
-	  lnum += 3
-	  b:result = 42
-
-- Insert white space in expressions where needed.
-- Change "." used for concatenation to "..".
-
-  For example, legacy function: >
-	  echo line(1).line(2)
-<  Becomes: >
-	  echo line(1) .. line(2)
-
-- line continuation does not always require a backslash: >
-	echo ['one',
-		\ 'two',
-		\ 'three'
-		\ ]
-<  Becomes: >
-	echo ['one',
-		'two',
-		'three'
-		]
-
-
-Calling a function in an expr option ~
-							*expr-option-function*
-The value of a few options, such as 'foldexpr', is an expression that is
-evaluated to get a value.  The evaluation can have quite a bit of overhead.
-One way to minimize the overhead, and also to keep the option value very
-simple, is to define a compiled function and set the option to call it
-without arguments.  Example: >
-	vim9script
-	def MyFoldFunc(): any
-	   ... compute fold level for line v:lnum
-	   return level
-	enddef
-	set foldexpr=s:MyFoldFunc()
-
-==============================================================================
-
-4. Types					*vim9-types*
-					*E1008* *E1009* *E1010* *E1012*
-					*E1013* *E1029* *E1030*
-The following builtin types are supported:
-	bool
-	number
-	float
-	string
-	blob
-	list<{type}>
-	dict<{type}>
-	job
-	channel
-	func
-	func: {type}
-	func({type}, ...)
-	func({type}, ...): {type}
-	void
-
-Not supported yet:
-	tuple<a: {type}, b: {type}, ...>
-
-These types can be used in declarations, but no simple value will actually
-have the "void" type.  Trying to use a void (e.g. a function without a
-return value) results in error *E1031*  *E1186* .
-
-There is no array type, use list<{type}> instead.  For a list constant an
-efficient implementation is used that avoids allocating a lot of small pieces
-of memory.
-							*E1005* *E1007*
-A partial and function can be declared in more or less specific ways:
-func				any kind of function reference, no type
-				checking for arguments or return value
-func: void			any number and type of arguments, no return
-				value
-func: {type}			any number and type of arguments with specific
-				return type
-
-func()				function with no argument, does not return a
-				value
-func(): void			same
-func(): {type}			function with no argument and return type
-
-func({type})			function with argument type, does not return
-				a value
-func({type}): {type}		function with argument type and return type
-func(?{type})			function with type of optional argument, does
-				not return a value
-func(...{type})			function with type of variable number of
-				arguments, does not return a value
-func({type}, ?{type}, ...{type}): {type}
-				function with:
-				- type of mandatory argument
-				- type of optional argument
-				- type of variable number of arguments
-				- return type
-
-If the return type is "void" the function does not return a value.
-
-The reference can also be a |Partial|, in which case it stores extra arguments
-and/or a dictionary, which are not visible to the caller.  Since they are
-called in the same way the declaration is the same.
-
-Custom types can be defined with `:type`: >
-	:type MyList list<string>
-Custom types must start with a capital letter, to avoid name clashes with
-builtin types added later, similarly to user functions.
-{not implemented yet}
-
-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.
-
-Global, buffer, window and tab page variables do not have a specific type, the
-value can be changed at any time, possibly changing the type.  Therefore, in
-compiled code the "any" type is assumed.
-
-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]
-At compile time Vim doesn't know the type of "g:two" and the expression type
-becomes list<any>.  An instruction is generated to check the list type before
-doing the assignment, which is a bit inefficient.
-						*type-casting* *E1104*
-To avoid this, use a type cast: >
-	var l: list<number> = [1, <number>g:two]
-The compiled code will then only check that "g:two" is a number and give an
-error if it isn't.  This is called type casting.
-
-The syntax of a type cast is:  "<" {type} ">".  There cannot be white space
-after the "<" or before the ">" (to avoid them being confused with
-smaller-than and bigger-than operators).
-
-The semantics is that, if needed, a runtime type check is performed.  The
-value is not actually changed.  If you need to change the type, e.g. to change
-it to a string, use the |string()| function.  Or use |str2nr()| to convert a
-string to a number.
-
-If a type is given where it is not expected you can get *E1272* .
-
-If a type is incomplete you get *E1363*, e.g. when you have an object for
-which the class is not known (usually that is a null object).
-
-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
-dictionary.  If there is a mix of types, the "any" type is used. >
-	[1, 2, 3]	list<number>
-	['a', 'b', 'c']	list<string>
-	[1, 'x', 3]	list<any>
-
-The common type of function references, if they do not all have the same
-number of arguments, uses "(...)" to indicate the number of arguments is not
-specified.  For example: >
-	def Foo(x: bool)
-	enddef
-	def Bar(x: bool, y: bool)
-	enddef
-	var funclist = [Foo, Bar]
-	echo funclist->typename()
-Results in:
-	list<func(...)>
-
-For script-local variables in Vim9 script the type is checked, also when the
-variable was declared in a legacy function.
-
-When a type has been declared this is attached to a List or Dictionary.  When
-later some expression attempts to change the type an error will be given: >
-	var ll: list<number> = [1, 2, 3]
-	ll->extend(['x'])  # Error, 'x' is not a number
-
-If the type is not declared then it is allowed to change: >
-	[1, 2, 3]->extend(['x'])  # result: [1, 2, 3, 'x']
-
-For a variable declaration an inferred type matters: >
-	var ll = [1, 2, 3]
-	ll->extend(['x'])  # Error, 'x' is not a number
-That is because the declaration looks like a list of numbers, thus is
-equivalent to: >
-	var ll: list<number> = [1, 2, 3]
-If you do want a more permissive list you need to declare the type: >
-	var ll: list<any> = [1, 2, 3]
-	ll->extend(['x'])  # OK
-
-
-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 (and no error message) if the
-string doesn't start with a number.  Quite often this leads to hard-to-find
-bugs. e.g.: >
-	echo 123 == '123'
-<	1 ~
-With an accidental space: >
-	echo 123 == ' 123'
-<	0 ~
-							*E1206* *E1210* *E1212*
-In Vim9 script this has been made stricter.  In most places it works just as
-before if the value used matches the expected type.  There will sometimes be
-an error, thus breaking backwards compatibility.  For example:
-- Using a number other than 0 or 1 where a boolean is expected.  *E1023*
-- Using a string value when setting a number option.
-- Using a number where a string is expected.   *E1024* *E1105*
-
-One consequence is that the item type of a list or dict given to |map()| must
-not change, if the type was declared.  This will give an error in Vim9
-script: >
-	var mylist: list<number> = [1, 2, 3]
-	echo map(mylist, (i, v) => 'item ' .. i)
-<	E1012: Type mismatch; expected number but got string in map() ~
-
-Instead use |mapnew()|, it creates a new list: >
-	var mylist: list<number> = [1, 2, 3]
-	echo mapnew(mylist, (i, v) => 'item ' .. i)
-<	['item 0', 'item 1', 'item 2'] ~
-
-If the item type was not declared or determined to be "any" it can change to a
-more specific type.  E.g. when a list of mixed types gets changed to a list of
-strings: >
-	var mylist = [1, 2.0, '3']
-	# typename(mylist) == "list<any>"
-	map(mylist, (i, v) => 'item ' .. i)
-	# typename(mylist) == "list<string>", no error
-
-There is a subtle difference between using a list constant directly and
-through a variable declaration.  Because of type inference, when using a list
-constant to initialize a variable, this also sets the declared type: >
-	var mylist = [1, 2, 3]
-	# typename(mylist) == "list<number>"
-	echo map(mylist, (i, v) => 'item ' .. i)  # Error!
-
-When using the list constant directly, the type is not declared and is allowed
-to change: >
-	echo map([1, 2, 3], (i, v) => 'item ' .. i)  # OK
-
-The reasoning behind this is that when a type is declared and the list is
-passed around and changed, the declaration must always hold.  So that you can
-rely on the type to match the declared type.  For a constant this is not
-needed.
-
-								*E1158*
-Same for |extend()|, use |extendnew()| instead, and for |flatten()|, use
-|flattennew()| instead.  Since |flatten()| is intended to always change the
-type, it can not be used in Vim9 script.
-
-			 *E1211* *E1217* *E1218* *E1219* *E1220* *E1221*
-			 *E1222* *E1223* *E1224* *E1225* *E1226* *E1227*
-			 *E1228* *E1238* *E1250* *E1251* *E1252* *E1256*
-			 *E1297* *E1298* *E1301*
-Types are checked for most builtin functions to make it easier to spot
-mistakes.
-
-==============================================================================
-
-5. Namespace, Import and Export
-					*vim9script* *vim9-export* *vim9-import*
-
-A Vim9 script can be written to be imported.  This means that some items are
-intentionally exported, made available to other scripts.  When the exporting
-script is imported in another script, these exported items can then be used in
-that script.  All the other items remain script-local in the exporting script
-and cannot be accessed by the importing script.
-
-This mechanism exists for writing a script that can be sourced (imported) by
-other scripts, while making sure these other scripts only have access to what
-you want them to.  This also avoids using the global namespace, which has a
-risk of name collisions.  For example when you have two plugins with similar
-functionality.
-
-You can cheat by using the global namespace explicitly.  That should be done
-only for things that really are global.
-
-
-Namespace ~
-							*vim9-namespace*
-To recognize a file that can be imported the `vim9script` statement must
-appear as the first statement in the file (see |vim9-mix| for an exception).
-It tells Vim to interpret the 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.
-							*E1101*
-The variables at the file level are very much like the script-local "s:"
-variables in legacy Vim script, but the "s:" is omitted.  And they cannot be
-deleted.
-
-In Vim9 script the global "g:" namespace can still be used as before.  And the
-"w:", "b:" and "t:" namespaces.  These have in common that variables are not
-declared, have no specific type and they can be deleted.  *E1304*
-
-A side effect of `:vim9script` is that the 'cpoptions' option is set to the
-Vim default value, like with: >
-	:set cpo&vim
-One of the effects is that |line-continuation| is always enabled.
-The original value of 'cpoptions' is restored at the end of the script, while
-flags added or removed in the script are also added to or removed from the
-original value to get the same effect.  The order of flags may change.
-In the |vimrc| file sourced on startup this does not happen.
-
-							*vim9-mix*
-There is one way to use both legacy and Vim9 syntax in one script file: >
-	" comments may go here
-	if !has('vim9script')
-	   " legacy script commands go here
-	   finish
-	endif
-	vim9script
-	# Vim9 script commands go here
-This allows for writing a script that takes advantage of the Vim9 script
-syntax if possible, but will also work on a Vim version without it.
-
-This can only work in two ways:
-1. The "if" statement evaluates to false, the commands up to `endif` are
-   skipped and `vim9script` is then the first command actually executed.
-2. The "if" statement evaluates to true, the commands up to `endif` are
-   executed and `finish` bails out before reaching `vim9script`.
-
-
-Export ~
-							*: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 ...
-	export interface MyClass ...
-<							*E1043* *E1044*
-As this suggests, only constants, variables, `:def` functions and classes can
-be exported. {not implemented yet: class, interface}
-
-							*E1042*
-`:export` can only be used in Vim9 script, at the script level.
-
-
-Import ~
-				*:import* *:imp* *E1094* *E1047* *E1262*
-				*E1048* *E1049* *E1053* *E1071* *E1088* *E1236*
-The exported items can be imported in another script. The import syntax has
-two forms. The simple form: >
-	import {filename}
-<
-Where {filename} is an expression that must evaluate to a string.  In this
-form the filename should end in ".vim" and the portion before ".vim" will
-become the script local name of the namespace. For example: >
-	import "myscript.vim"
-<
-This makes each exported item in "myscript.vim" available as "myscript.item".
-						*:import-as* *E1257* *E1261*
-In case the name is long or ambiguous, this form can be used to specify
-another name: >
-	import {longfilename} as {name}
-<
-In this form {name} becomes a specific script local name for the imported
-namespace.  Therefore {name} must consist of letters, digits and '_', like
-|internal-variables|.  The {longfilename} expression must evaluate to any
-filename.  For example: >
-	import "thatscript.vim.v2" as that
-<						*E1060* *E1258* *E1259* *E1260*
-Then you can use "that.item", etc.  You are free to choose the name "that".
-Use something that will be recognized as referring to the imported script.
-Avoid command names, command modifiers and builtin function names, because the
-name will shadow them.  Better not start the name starts with a capital
-letter, since it can then also shadow global user commands and functions.
-Also, you cannot use the name for something else in the script, such as a
-function or variable name.
-
-In case the dot in the name is undesired, a local reference can be made for a
-function: >
-	var LongFunc = that.LongFuncName
-
-This also works for constants: >
-	const MAXLEN = that.MAX_LEN_OF_NAME
-
-This does not work for variables, since the value would be copied once and
-when changing the variable the copy will change, not the original variable.
-You will need to use the full name, with the dot.
-
-`:import` can not be used in a function.  Imported items are intended to exist
-at the script level and only imported once.
-
-The script name after `import` can be:
-- A relative path, starting "." or "..".  This finds a file relative to the
-  location of the script file itself.  This is useful to split up a large
-  plugin into several files.
-- An absolute path, starting with "/" on Unix or "D:/" on MS-Windows.  This
-  will rarely be used.
-- A path not being relative or absolute.  This will be found in the
-  "import" subdirectories of 'runtimepath' entries.  The name will usually be
-  longer and unique, to avoid loading the wrong file.
-  Note that "after/import" is not used.
-
-If the name does not end in ".vim" then the use of "as name" is required.
-
-Once a vim9 script file has been imported, the result is cached and used the
-next time the same script is imported.  It will not be read again.
-
-It is not allowed to import the same script twice, also when using two
-different "as" names.
-
-When using the imported name the dot and the item name must be in the same
-line, there can be no line break: >
-	echo that.
-		name   # Error!
-	echo that
-		.name  # Error!
-<						*import-map*
-When you've imported a function from one script into a vim9 script you can
-refer to the imported function in a mapping by prefixing it with |<SID>|: >
-	noremap <silent> ,a :call <SID>name.Function()<CR>
-
-When the mapping is defined "<SID>name." will be replaced with <SNR> and the
-script ID of the imported script.
-An even simpler solution is using |<ScriptCmd>|: >
-	noremap ,a <ScriptCmd>name.Function()<CR>
-
-Note that this does not work for variables, only for functions.
-
-					    *import-legacy* *legacy-import*
-`:import` can also be used in legacy Vim script.  The imported namespace still
-becomes script-local, even when the "s:" prefix is not given. For example: >
-        import "myfile.vim"
-	call s:myfile.MyFunc()
-
-And using the "as name" form: >
-	import "otherfile.vim9script" as that
-	call s:that.OtherFunc()
-
-However, the namespace cannot be resolved on its own: >
-	import "that.vim"
-	echo s:that
-	" ERROR: E1060: Expected dot after name: s:that
-<
-This also affects the use of |<SID>| in the legacy mapping context.  Since
-|<SID>| is only a valid prefix for a function and NOT for a namespace, you
-cannot use it
-to scope a function in a script local namespace. Instead of prefixing the
-function with |<SID>| you should use|<ScriptCmd>|. For example: >
-	noremap ,a <ScriptCmd>:call s:that.OtherFunc()<CR>
-<
-							*:import-cycle*
-The `import` commands are executed when encountered.  If script A imports
-script B, and B (directly or indirectly) imports A, this will be skipped over.
-At this point items in A after "import B" will not have been processed and
-defined yet.  Therefore cyclic imports can exist and not result in an error
-directly, but may result in an error for items in A after "import B" not being
-defined.  This does not apply to autoload imports, see the next section.
-
-
-Importing an autoload script ~
-					*vim9-autoload* *import-autoload*
-For optimal startup speed, loading scripts should be postponed until they are
-actually needed.  Using the autoload mechanism is recommended:
-							*E1264*
-1. In the plugin define user commands, functions and/or mappings that refer to
-   items imported from an autoload script. >
-	import autoload 'for/search.vim'
-	command -nargs=1 SearchForStuff search.Stuff(<f-args>)
-
-<   This goes in .../plugin/anyname.vim.  "anyname.vim" can be freely chosen.
-   The "SearchForStuff" command is now available to the user.
-
-   The "autoload" argument to `:import` means that the script is not loaded
-   until one of the items is actually used.  The script will be found under
-   the "autoload" directory in 'runtimepath' instead of the "import"
-   directory.  Alternatively a relative or absolute name can be used, see
-   below.
-
-2. In the autoload script put the bulk of the code. >
-	vim9script
-	export def Stuff(arg: string)
-	  ...
-
-<   This goes in .../autoload/for/search.vim.
-
-   Putting the "search.vim" script under the "/autoload/for/" directory has
-   the effect that "for#search#" will be prefixed to every exported item.  The
-   prefix is obtained from the file name, as you would to manually in a
-   legacy autoload script.  Thus the exported function can be found with
-   "for#search#Stuff", but you would normally use `import autoload` and not
-   use the prefix (which has the side effect of loading the autoload script
-   when compiling a function that encounters this name).
-
-   You can split up the functionality and import other scripts from the
-   autoload script as you like.  This way you can share code between plugins.
-
-Searching for the autoload script in all entries in 'runtimepath' can be a bit
-slow.  If the plugin knows where the script is located, quite often a relative
-path can be used.  This avoids the search and should be quite a bit faster.
-Another advantage is that the script name does not need to be unique.  An
-absolute path is also possible.  Examples: >
-	import autoload '../lib/implement.vim'
-	import autoload MyScriptsDir .. '/lib/implement.vim'
-
-For defining a mapping that uses the imported autoload script the special key
-|<ScriptCmd>| is useful.  It allows for a command in a mapping to use the
-script context of where the mapping was defined.
-
-When compiling a `:def` function and a function in an autoload script is
-encountered, the script is not loaded until the `:def` function is called.
-This also means you get any errors only at runtime, since the argument and
-return types are not known yet.  If you would use the name with '#' characters
-then the autoload script IS loaded.
-
-Be careful to not refer to an item in an autoload script that does trigger
-loading it unintentionally.  For example, when setting an option that takes a
-function name, make sure to use a string, not a function reference: >
-	import autoload 'qftf.vim'
-	&quickfixtextfunc = 'qftf.Func'  # autoload script NOT loaded
-	&quickfixtextfunc = qftf.Func    # autoload script IS loaded
-On the other hand, it can be useful to load the script early, at a time when
-any errors should be given.
-
-For testing the |test_override()| function can be used to have the
-`import autoload` load the script right away, so that the items and types can
-be checked without waiting for them to be actually used: >
-	test_override('autoload', 1)
-Reset it later with: >
-	test_override('autoload', 0)
-Or: >
-	test_override('ALL', 0)
-
-
-==============================================================================
-
-6. Classes and interfaces				*vim9-classes*
-
-In legacy script a Dictionary could be used as a kind-of object, by adding
-members that are functions.  However, this is quite inefficient and requires
-the writer to do the work of making sure all the objects have the right
-members.  See |Dictionary-function|.
-
-In |Vim9| script you can have classes, objects and interfaces like in most
-popular object-oriented programming languages.  Since this is a lot of
-functionality it is located in a separate help file: |vim9class.txt|.
-
-
-==============================================================================
-
-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
-need to be handled, such as error messages and exceptions.  The need to create
-a dictionary for a: and l: scopes, the a:000 list and several others add too
-much overhead that cannot be avoided.
-
-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.
-
-
-Type checking ~
-
-When compiling lines of Vim commands into instructions as much as possible
-should be done at compile time.  Postponing it to runtime makes the execution
-slower and means mistakes are found only later.  For example, when
-encountering the "+" character and compiling this into a generic add
-instruction, at runtime the instruction would have to inspect the type 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 evaluating an
-  expression.
-- 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 also used by 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
-  goes against legacy Vim script and often leads to mistakes.  For that reason
-  we will keep using ".." for string concatenation.  Lua also uses ".." this
-  way.  And it allows for conversion to string for more values.
-- 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.  The |falsy-operator| was added for the mechanism to use a
-  default value.
-- 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.
-- TypeScript has various "Readonly" types, which have limited usefulness,
-  since a type cast can remove the immutable nature.  Vim locks the value,
-  which is more flexible, but is only checked at runtime.
-- TypeScript has a complicated "import" statement that does not match how the
-  Vim import mechanism works.  A much simpler mechanism is used instead, which
-  matches that the imported script is only sourced once.
-
-
-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 varies.  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 have 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 other languages are doing.
-Some details are unexpected and can be improved.  For example a boolean
-condition would accept a string, convert it to a number and check if the
-number is non-zero.  This is unexpected and often leads to mistakes, since
-text not starting with a number would be converted to zero, which is
-considered false.  Thus using a string for a condition would often not give an
-error and be considered false.  That is confusing.
-
-In Vim9 type checking is stricter to avoid mistakes.  Where a condition is
-used, e.g. with the `:if` command and the `||` operator, only boolean-like
-values are accepted:
-	true:  `true`, `v:true`, `1`, `0 < 9`
-	false: `false`, `v:false`, `0`, `0 > 9`
-Note that the number zero is false and the number one is true.  This is more
-permissive than most other languages.  It was done because many builtin
-functions return these values, and changing that causes more problems than it
-solves.  After using this for a while it turned out to work well.
-
-If you have any type of value and want to use it as a boolean, use the `!!`
-operator:
-	true: `!!'text'`   `!![99]`   `!!{'x': 1}`   `!!99`
-	false: `!!''`   `!![]`   `!!{}`
-
-From a language like JavaScript we have this handy construct: >
-	GetName() || 'unknown'
-However, this conflicts with only allowing a boolean for a condition.
-Therefore the "??" operator was added: >
-	GetName() ?? 'unknown'
-Here you can explicitly express your intention to use the value as-is and not
-result in a boolean. This is called the |falsy-operator|.
-
-
-Import and Export ~
-
-A problem of legacy Vim script is that by default all functions and variables
-are global.  It is possible to make them script-local, but then they are not
-available in other scripts.  This defies the concept of a package that only
-exports selected items and keeps the rest local.
-
-In Vim9 script a mechanism very similar to the JavaScript import and export
-mechanism is supported.  It is a variant to the existing `:source` command
-that works like one would expect:
-- Instead of making everything global by default, everything is script-local,
-  some of these are exported.
-- When importing a script the symbols that are imported are explicitly listed,
-  avoiding name conflicts and failures if functionality is added later.
-- The mechanism allows for writing a big, long script with a very clear API:
-  the exported functions, variables and classes.
-- By using relative paths loading can be much faster for an import inside of a
-  package, no need to search many directories.
-- Once an import has been used, its items are cached and loading it again is
-  not needed.
-- The Vim-specific use of "s:" to make things script-local can be dropped.
-
-When sourcing a Vim9 script (from a Vim9 or legacy script), only the items
-defined globally can be used, not the exported items.  Alternatives
-considered:
-- All the exported items become available as script-local items.  This makes
-  it uncontrollable what items get defined and likely soon leads to trouble.
-- Use the exported items and make them global.  Disadvantage is that it's then
-  not possible to avoid name clashes in the global namespace.
-- Completely disallow sourcing a Vim9 script, require using `:import`.  That
-  makes it difficult to use scripts for testing, or sourcing them from the
-  command line to try them out.
-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 well.
-
-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, a `:defcompile` command at the end of the script will help out.
-
-
-Why not use an existing 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 process, 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.
-
-
-
- vim:tw=78:ts=8:noet:ft=help:norl:
+*vim9.txt*	For Vim version 9.0.  Last change: 2023 Jun 10
+
+
+		  VIM REFERENCE MANUAL	  by Bram Moolenaar
+
+
+Vim9 script commands and expressions.			*Vim9* *vim9*
+
+Most expression help is in |eval.txt|.  This file is about the new syntax and
+features in Vim9 script.
+
+
+
+1.  What is Vim9 script?		|Vim9-script|
+2.  Differences				|vim9-differences|
+3.  New style functions			|fast-functions|
+4.  Types				|vim9-types|
+5.  Namespace, Import and Export	|vim9script|
+6.  Classes and interfaces		|vim9-classes|
+
+9.  Rationale				|vim9-rationale|
+
+==============================================================================
+
+1. What is Vim9 script?					*Vim9-script*
+
+Vim script has been growing over time, while preserving backwards
+compatibility.  That means bad choices from the past often can't be changed
+and compatibility with Vi restricts possible solutions.  Execution is quite
+slow, each line is parsed every time it is executed.
+
+The main goal of Vim9 script is to drastically improve performance.  This is
+accomplished by compiling commands into instructions that can be efficiently
+executed.  An increase in execution speed of 10 to 100 times can be expected.
+
+A secondary goal is to avoid Vim-specific constructs and get closer to
+commonly used programming languages, such as JavaScript, TypeScript and Java.
+
+The performance improvements can only be achieved by not being 100% backwards
+compatible.  For example, making function arguments available in the "a:"
+dictionary adds quite a lot of overhead.  In a Vim9 function this dictionary
+is not available.  Other differences are more subtle, such as how errors are
+handled.
+
+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
+- a command prefixed with the `vim9cmd` command modifier
+
+When using `:function` in a Vim9 script file the legacy syntax is used, with
+the highest |scriptversion|.  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.
+
+:vim9[cmd] {cmd}				*:vim9* *:vim9cmd* *E1164*
+		Evaluate and execute {cmd} using Vim9 script syntax and
+		semantics.  Useful when typing a command and in a legacy
+		script or function.
+
+:leg[acy] {cmd}					*:leg* *:legacy* *E1189* *E1234*
+		Evaluate and execute {cmd} using legacy script syntax and
+		semantics.  Only useful in a Vim9 script or a :def function.
+		Note that {cmd} cannot use local variables, since it is parsed
+		with legacy expression syntax.
+
+==============================================================================
+
+2. Differences from legacy Vim script			*vim9-differences*
+
+Overview ~
+							*E1146*
+Brief summary of the differences you will most often encounter when using Vim9
+script and `:def` functions; details are below:
+- Comments start with #, not ": >
+	echo "hello"   # comment
+- Using a backslash for line continuation is hardly ever needed: >
+	echo "hello "
+	     .. yourName
+	     .. ", how are you?"
+- White space is required in many places to improve readability.
+- Assign values without `:let` *E1126* , declare variables with `:var`: >
+	var count = 0
+	count += 3
+- Constants can be declared with `:final` and `:const`: >
+	final matches = []		  # add to the list later
+	const names = ['Betty', 'Peter']  # cannot be changed
+- `:final` cannot be used as an abbreviation of `:finally`.
+- Variables and functions are script-local by default.
+- Functions are declared with argument types and return type: >
+	def CallMe(count: number, message: string): bool
+- Call functions without `:call`: >
+	writefile(['done'], 'file.txt')
+- You cannot use old Ex commands:
+	`:Print`
+	`:append`
+	`:change`
+	`:d`  directly followed by 'd' or 'p'.
+	`:insert`
+	`:k`
+	`:mode`
+	`:open`
+	`:s`  with only flags
+	`:t`
+	`:xit`
+- Some commands, especially those used for flow control, cannot be shortened.
+  E.g., `:throw` cannot be written as `:th`.  *vim9-no-shorten*
+- You cannot use curly-braces names.
+- A range before a command must be prefixed with a colon: >
+	:%s/this/that
+- Executing a register with "@r" does not work, you can prepend a colon or use
+  `:exe`: >
+	:exe @a
+- Unless mentioned specifically, the highest |scriptversion| is used.
+- When defining an expression mapping, the expression will be evaluated in the
+  context of the script where it was defined.
+- When indexing a string the index is counted in characters, not bytes:
+  |vim9-string-index|
+- Some possibly unexpected differences: |vim9-gotchas|.
+
+
+Comments starting with # ~
+
+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
+to tell what the meaning is, since both a string and a comment can be followed
+by arbitrary text.  To avoid confusion only # comments are recognized.  This
+is the same as in shell scripts and Python programs.
+
+In Vi # is a command to list text with numbers.  In Vim9 script you can use
+`:number` for that. >
+	:101 number
+
+To improve readability there must be a space between a command and the #
+that starts a comment: >
+	var name = value # comment
+	var name = value# error!
+<							*E1170*
+Do not start a comment with #{, it looks like the legacy dictionary literal
+and produces an error where this might be confusing.  #{{ or #{{{ are OK,
+these can be used to start a fold.
+
+When starting to read a script file Vim doesn't know it is |Vim9| script until
+the `vim9script` command is found.  Until that point you would need to use
+legacy comments: >
+	" legacy comment
+	vim9script
+	# Vim9 comment
+
+That looks ugly, better put `vim9script` in the very first line: >
+	vim9script
+	# Vim9 comment
+
+In legacy Vim script # is also used for the alternate file name.  In Vim9
+script you need to use %% instead.  Instead of ## use %%% (stands for all
+arguments).
+
+
+Vim9 functions ~
+							*E1099*
+A function defined with `:def` is compiled.  Execution is many times faster,
+often 10 to 100 times.
+
+Many errors are already found when compiling, before the function is executed.
+The syntax is strict, to enforce code that is easy to read and understand.
+
+Compilation is done when any of these is encountered:
+- the first time the function is called
+- when the `:defcompile` command is encountered in the script after the
+  function was defined
+- `:disassemble` is used for the function.
+- a function that is compiled calls the function or uses it as a function
+  reference (so that the argument and return types can be checked)
+						*E1091* *E1191*
+If compilation fails it is not tried again on the next call, instead this
+error is given: "E1091: Function is not compiled: {name}".
+Compilation will fail when encountering a user command that has not been
+created yet.  In this case you can call `execute()` to invoke it at runtime. >
+	def MyFunc()
+	  execute('DefinedLater')
+	enddef
+
+`:def` has no options like `:function` does: "range", "abort", "dict" or
+"closure".  A `:def` function always aborts on an error (unless `:silent!` was
+used for the command or the error was caught a `:try` block), does not get a
+range passed, cannot be a "dict" function, and can always be a closure.
+						*vim9-no-dict-function*
+You can use a Vim9 Class (|Vim9-class|) instead of a "dict function".
+You can also pass the dictionary explicitly: >
+	def DictFunc(self: dict<any>, arg: string)
+	   echo self[arg]
+	enddef
+	var ad = {item: 'value', func: DictFunc}
+	ad.func(ad, 'item')
+
+You can call a legacy dict function though: >
+	func Legacy() dict
+	  echo self.value
+	endfunc
+	def CallLegacy()
+	  var d = {func: Legacy, value: 'text'}
+	  d.func()
+	enddef
+<						*E1096* *E1174* *E1175*
+The argument types and return type need to be specified.  The "any" type can
+be used, type checking will then be done at runtime, like with legacy
+functions.
+							*E1106*
+Arguments are accessed by name, without "a:", just like any other language.
+There is no "a:" dictionary or "a:000" list.
+			*vim9-variable-arguments* *E1055* *E1160* *E1180*
+Variable arguments are defined as the last argument, with a name and have a
+list type, similar to TypeScript.  For example, a list of numbers: >
+	def MyFunc(...itemlist: list<number>)
+	   for item in itemlist
+	     ...
+
+When a function argument is optional (it has a default value) passing `v:none`
+as the argument results in using the default value.  This is useful when you
+want to specify a value for an argument that comes after an argument that
+should use its default value.  Example: >
+	def MyFunc(one = 'one', last = 'last')
+	  ...
+	enddef
+	MyFunc(v:none, 'LAST')  # first argument uses default value 'one'
+<
+					*vim9-ignored-argument* *E1181*
+The argument "_" (an underscore) can be used to ignore the argument.  This is
+most useful in callbacks where you don't need it, but do need to give an
+argument to match the call.  E.g. when using map() two arguments are passed,
+the key and the value, to ignore the key: >
+	map(numberList, (_, v) => v * 2)
+There is no error for using the "_" argument multiple times.  No type needs to
+be given.
+
+
+Functions and variables are script-local by default ~
+							*vim9-scopes*
+When using `:function` or `:def` to specify a new function at the script level
+in a Vim9 script, the function is local to the script.  Like prefixing "s:" in
+legacy script.  To define a global function or variable the "g:" prefix must
+be used.  For functions in a script that is to be imported and in an autoload
+script "export" needs to be used for those to be used elsewhere. >
+	def ThisFunction()          # script-local
+	def g:ThatFunction()        # global
+	export def Function()       # for import and import autoload
+<						*E1058* *E1075*
+When using `:function` or `:def` to specify a nested function inside a `:def`
+function and no namespace was given, this nested function is local to the code
+block it is defined in.  It cannot be used in `function()` with a string
+argument, pass the function reference itself: >
+	def Outer()
+	  def Inner()
+	    echo 'inner'
+	  enddef
+	  var Fok = function(Inner)     # OK
+	  var Fbad = function('Inner')  # does not work
+
+Detail: this is because "Inner" will actually become a function reference to a
+function with a generated name.
+
+It is not possible to define a script-local function in a function.  You can
+define a local function and assign it to a script-local Funcref (it must have
+been declared at the script level).  It is possible to define a global
+function by using the "g:" prefix.
+
+When referring to a function and no "s:" or "g:" prefix is used, Vim will
+search for the function:
+- in the function scope, in block scopes
+- in the script scope
+
+Imported functions are found with the prefix from the `:import` command.
+
+Since a script-local function reference can be used without "s:" the name must
+start with an upper case letter even when using the "s:" prefix.  In legacy
+script "s:funcref" could be used, because it could not be referred to with
+"funcref".  In Vim9 script it can, therefore "s:Funcref" must be used to avoid
+that the name interferes with builtin functions.
+						*vim9-s-namespace* *E1268*
+The use of the "s:" prefix is not supported at the Vim9 script level.  All
+functions and variables without a prefix are script-local.
+
+In :def functions the use of "s:" depends on the script: Script-local
+variables and functions in a legacy script do use "s:", while in a Vim9 script
+they do not use "s:".  This matches what you see in the rest of the file.
+
+In legacy functions the use of "s:" for script items is required, as before.
+No matter if the script is Vim9 or legacy.
+
+In all cases the function must be defined before used.  That is when it is
+called, when `:defcompile` causes it to be compiled, or when code that calls
+it is being compiled (to figure out the return type).
+
+The result is that functions and variables without a namespace can usually be
+found in the script, either defined there or imported.  Global functions and
+variables could be defined anywhere (good luck finding out where!  You can
+often see where it was last set using |:verbose|).
+							*E1102*
+Global functions can still be defined and deleted at nearly any time.  In
+Vim9 script script-local functions are defined once when the script is sourced
+and cannot be deleted or replaced by itself (it can be by reloading the
+script).
+
+When compiling a function and a function call is encountered for a function
+that is not (yet) defined, the |FuncUndefined| autocommand is not triggered.
+You can use an autoload function if needed, or call a legacy function and have
+|FuncUndefined| triggered there.
+
+
+Reloading a Vim9 script clears functions and variables by default ~
+						*vim9-reload* *E1149* *E1150*
+When loading a legacy Vim script a second time nothing is removed, the
+commands will replace existing variables and functions, create new ones, and
+leave removed things hanging around.
+
+When loading a Vim9 script a second time all existing script-local functions
+and variables are deleted, thus you start with a clean slate.  This is useful
+if you are developing a plugin and want to try a new version.  If you renamed
+something you don't have to worry about the old name still hanging around.
+
+If you do want to keep items, use: >
+	vim9script noclear
+
+You want to use this in scripts that use a `finish` command to bail out at
+some point when loaded again.  E.g. when a buffer local option is set to a
+function, the function does not need to be defined more than once: >
+	vim9script noclear
+	setlocal completefunc=SomeFunc
+	if exists('*SomeFunc')
+	  finish
+	endif
+	def SomeFunc()
+	....
+
+
+Variable declarations with :var, :final and :const ~
+				*vim9-declaration* *:var* *E1079*
+				*E1017* *E1020* *E1054* *E1087* *E1124*
+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
+	   inner = 0
+	endif
+	echo inner
+
+Although this is shorter and faster for simple values: >
+	var inner = 0
+	if cond
+	   inner = 5
+	endif
+	echo inner
+<							*E1025* *E1128*
+To intentionally hide a variable from code that follows, a block can be
+used: >
+	{
+	   var temp = 'temp'
+	   ...
+	}
+	echo temp  # Error!
+
+This is especially useful in a user command: >
+	command -range Rename {
+		 var save = @a
+		 @a = 'some expression'
+		 echo 'do something with ' .. @a
+		 @a = save
+	    }
+
+And with autocommands: >
+   au BufWritePre *.go {
+		 var save = winsaveview()
+		 silent! exe ':%! some formatting command'
+		 winrestview(save)
+	   }
+
+Although using a :def function probably works better.
+
+				*E1022* *E1103* *E1130* *E1131* *E1133*
+				*E1134*
+Declaring a variable with a type but without an initializer will initialize to
+false (for bool), empty (for string, list, dict, etc.) or zero (for number,
+any, etc.).  This matters especially when using the "any" type, the value will
+default to the number zero.  For example, when declaring a list, items can be
+added: >
+	var myList: list<number>
+	myList->add(7)
+
+Initializing a variable to a null value, e.g. `null_list`, differs from not
+initializing the variable.  This throws an error: >
+	var myList = null_list
+	myList->add(7)  # E1130: Cannot add to null list
+
+<						*E1016* *E1052* *E1066*
+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.  Those can also be deleted
+with `:unlet`.
+							*E1065*
+You cannot use `:va` to declare a variable, it must be written with the full
+name `:var`.  Just to make sure it is easy to read.
+							*E1178*
+`:lockvar` does not work on local variables.  Use `:const` and `:final`
+instead.
+
+The `exists()` and `exists_compiled()` functions do not work on local variables
+or arguments.
+				*E1006* *E1041* *E1167* *E1168* *E1213*
+Variables, functions and function arguments cannot shadow previously defined
+or imported variables and functions in the same script file.
+Variables may shadow Ex commands, rename the variable if needed.
+
+Global variables must be prefixed with "g:", also at the script level. >
+	vim9script
+	var script_local = 'text'
+	g:global = 'value'
+	var Funcref = g:ThatFunction
+
+Global functions must be prefixed with "g:": >
+	vim9script
+	def g:GlobalFunc(): string
+	  return 'text'
+	enddef
+	echo g:GlobalFunc()
+The "g:" prefix is not needed for auto-load functions.
+
+					*vim9-function-defined-later*
+Although global functions can be called without the "g:" prefix, they must
+exist when compiled.  By adding the "g:" prefix the function can be defined
+later.  Example: >
+	def CallPluginFunc()
+	  if exists('g:loaded_plugin')
+	    g:PluginFunc()
+	  endif
+	enddef
+
+If you do it like this, you get an error at compile time that "PluginFunc"
+does not exist, even when "g:loaded_plugin" does not exist: >
+	def CallPluginFunc()
+	  if exists('g:loaded_plugin')
+	    PluginFunc()   # Error - function not found
+	  endif
+	enddef
+
+You can use exists_compiled() to avoid the error, but then the function would
+not be called, even when "g:loaded_plugin" is defined later: >
+	def CallPluginFunc()
+	  if exists_compiled('g:loaded_plugin')
+	    PluginFunc()   # Function may never be called
+	  endif
+	enddef
+
+Since `&opt = value` is now assigning a value to option "opt", ":&" cannot be
+used to repeat a `:substitute` command.
+							*vim9-unpack-ignore*
+For an unpack assignment the underscore can be used to ignore a list item,
+similar to how a function argument can be ignored: >
+	[a, _, c] = theList
+To ignore any remaining items: >
+	[a, b; _] = longList
+<							*E1163* *E1080*
+Declaring more than one variable at a time, using the unpack notation, is
+possible.  Each variable can have a type or infer it from the value: >
+	var [v1: number, v2] = GetValues()
+Use this only when there is a list with values, declaring one variable per
+line is much easier to read and change later.
+
+
+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.
+							*E1021* *E1307*
+`: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!
+	myList->add(3)		# Error!
+<							*:final* *E1125*
+`: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
+	myList->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"
+
+
+Omitting :call and :eval ~
+							*E1190*
+Functions can be called without `:call`: >
+	writefile(lines, 'file')
+Using `:call` is still possible, but this is discouraged.
+
+A method call without `eval` is possible, so long as the start is an
+identifier or can't be an Ex command.  For a function either "(" or "->" must
+be following, without a line break.  Examples: >
+	myList->add(123)
+	g:myList->add(123)
+	[1, 2, 3]->Process()
+	{a: 1, b: 2}->Process()
+	"foobar"->Process()
+	("foobar")->Process()
+	'foobar'->Process()
+	('foobar')->Process()
+
+In the rare case there is ambiguity between a function name and an Ex command,
+prepend ":" to make clear you want to use the Ex command.  For example, there
+is both the `:substitute` command and the `substitute()` function.  When the
+line starts with `substitute(` this will use the function. Prepend a colon to
+use the command instead: >
+	:substitute(pattern (replacement (
+
+If the expression starts with "!" this is interpreted as a shell command, not
+negation of a condition.  Thus this is a shell command: >
+	!shellCommand->something
+Put the expression in parentheses to use the "!" for negation: >
+	(!expression)->Method()
+
+Note that while variables need to be defined before they can be used,
+functions can be called before being defined.  This is required to allow
+for cyclic dependencies between functions.  It is slightly less efficient,
+since the function has to be looked up by name.  And a typo in the function
+name will only be found when the function is called.
+
+
+Omitting function() ~
+
+A user defined function can be used as a function reference in an expression
+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 (including void).  The function can be
+defined later if the argument is in quotes.
+
+
+Lambda using => instead of -> ~
+							*vim9-lambda*
+In legacy script there can be confusion between using "->" for a method call
+and for a lambda.  Also, when a "{" is found the parser needs to figure out if
+it is the start of a lambda or a dictionary, which is now more complicated
+because of the use of argument types.
+
+To avoid these problems Vim9 script uses a different syntax for a lambda,
+which is similar to JavaScript: >
+	var Lambda = (arg) => expression
+	var Lambda = (arg): type => expression
+<							*E1157*
+No line break is allowed in the arguments of a lambda up to and including the
+"=>" (so that Vim can tell the difference between an expression in parentheses
+and lambda arguments).  This is OK: >
+	filter(list, (k, v) =>
+			v > 0)
+This does not work: >
+	filter(list, (k, v)
+			=> v > 0)
+This also does not work: >
+	filter(list, (k,
+			v) => v > 0)
+But you can use a backslash to concatenate the lines before parsing: >
+	filter(list, (k,
+		\	v)
+		\	=> v > 0)
+<					*vim9-lambda-arguments* *E1172*
+In legacy script a lambda could be called with any number of extra arguments,
+there was no way to warn for not using them.  In Vim9 script the number of
+arguments must match.  If you do want to accept any arguments, or any further
+arguments, use "..._", which makes the function accept
+|vim9-variable-arguments|.  Example: >
+	var Callback = (..._) => 'anything'
+	echo Callback(1, 2, 3)  # displays "anything"
+
+<						*inline-function* *E1171*
+Additionally, a lambda can contain statements in {}: >
+	var Lambda = (arg) => {
+		g:was_called = 'yes'
+		return expression
+	    }
+This can be useful for a timer, for example: >
+	var count = 0
+	var timer = timer_start(500, (_) => {
+		 count += 1
+		 echom 'Handler called ' .. count
+	     }, {repeat: 3})
+
+The ending "}" must be at the start of a line.  It can be followed by other
+characters, e.g.: >
+	var d = mapnew(dict, (k, v): string => {
+	     return 'value'
+	   })
+No command can follow the "{", only a comment can be used there.
+
+						*command-block* *E1026*
+The block can also be used for defining a user command.  Inside the block Vim9
+syntax will be used.
+
+If the statements include a dictionary, its closing bracket must not be
+written at the start of a line.  Otherwise, it would be parsed as the end of
+the block.  This does not work: >
+	command NewCommand {
+	     g:mydict = {
+	       'key': 'value',
+	       }  # ERROR: will be recognized as the end of the block
+	   }
+Put the '}' after the last item to avoid this: >
+	command NewCommand {
+	     g:mydict = {
+	       'key': 'value' }
+	   }
+
+Rationale: The "}" cannot be after a command because it would require parsing
+the commands to find it.  For consistency with that no command can follow the
+"{".  Unfortunately this means using "() => {  command  }" does not work, line
+breaks are always required.
+
+							*vim9-curly*
+To avoid the "{" of a dictionary literal to be recognized as a statement block
+wrap it in parentheses: >
+	var Lambda = (arg) => ({key: 42})
+
+Also when confused with the start of a command block: >
+	({
+	    key: value
+	 })->method()
+
+
+Automatic line continuation ~
+					*vim9-line-continuation* *E1097*
+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 (see
+|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,
+		}
+With a 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
+
+For commands that have an argument that is a list of commands, the | character
+at the start of the line indicates line continuation: >
+	autocmd BufNewFile *.match if condition
+		|   echo 'match'
+		| endif
+
+Note that this means that in heredoc the first line cannot start with a bar: >
+	var lines =<< trim END
+	   | this doesn't work
+	END
+Either use an empty line at the start or do not use heredoc.  Or temporarily
+add the "C" flag to 'cpoptions': >
+	set cpo+=C
+	var lines =<< trim END
+	   | this works
+	END
+	set cpo-=C
+If the heredoc is inside a function 'cpoptions' must be set before :def and
+restored after the :enddef.
+
+In places where line continuation with a backslash is still needed, such as
+splitting up a long Ex command, comments can start with '#\ ': >
+	syn region Text
+	      \ start='foo'
+	      #\ comment
+	      \ end='bar'
+Like with legacy script '"\ ' is used.  This is also needed when line
+continuation is used without a backslash and a line starts with a bar: >
+	au CursorHold * echom 'BEFORE bar'
+	      #\ some comment
+	      | echom 'AFTER bar'
+<
+							*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 example 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
+
+After the range an Ex command must follow.  Without the colon you can call a
+function without `:call`, but after a range you do need it: >
+	MyFunc()
+	:% call MyFunc()
+
+Note that the colon is not required for the |+cmd| argument: >
+	edit +6 fname
+
+It is also possible to split a function header over multiple lines, in between
+arguments: >
+	def MyFunc(
+		text: string,
+		separator = '-'
+		): string
+
+Since a continuation line cannot be easily recognized the parsing of commands
+has been made stricter.  E.g., because of the error in the first line, the
+second line is seen as a separate command: >
+	popup_create(some invalid expression, {
+	   exit_cb: Func})
+Now "exit_cb: Func})" is actually a valid command: save any changes to the
+file "_cb: Func})" and exit.  To avoid this kind of mistake in Vim9 script
+there must be white space between most command names and the argument.
+*E1144*
+
+However, the argument of a command that is a command won't be recognized.  For
+example, after "windo echo expr" a line break inside "expr" will not be seen.
+
+
+Notes:
+- "enddef" cannot be used at the start of a continuation line, it ends the
+  current function.
+- No line break is allowed in the LHS of an assignment.  Specifically when
+  unpacking a list |:let-unpack|. This is OK: >
+	[var1, var2] =
+		Func()
+<  This does not work: >
+	[var1,
+	    var2] =
+		Func()
+- No line break is allowed in between arguments of an `:echo`, `:execute` and
+  similar commands.  This is OK: >
+	echo [1,
+		2] [3,
+			4]
+<  This does not work: >
+	echo [1, 2]
+		[3, 4]
+- In some cases it is difficult for Vim to parse a command, especially when
+  commands are used as an argument to another command, such as `:windo`.  In
+  those cases the line continuation with a backslash has to be used.
+
+
+White space ~
+			*E1004* *E1068* *E1069* *E1074* *E1127* *E1202*
+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.
+
+White space is required in a sublist (list slice) around the ":", except at
+the start and end: >
+	otherlist = mylist[v : count]	# v:count has a different meaning
+	otherlist = mylist[:]		# make a copy of the List
+	otherlist = mylist[v :]
+	otherlist = mylist[: v]
+
+White space is not allowed:
+- Between a function name and the "(": >
+	Func (arg)	   # Error!
+	Func
+	     \ (arg)	   # Error!
+	Func
+	      (arg)	   # Error!
+	Func(arg)	   # OK
+	Func(
+	      arg)	   # OK
+	Func(
+	      arg	   # OK
+	      )
+<							*E1205*
+White space is not allowed in a `:set` command between the option name and a
+following "&", "!", "<", "=", "+=", "-=" or "^=".
+
+
+No curly braces expansion ~
+
+|curly-braces-names| cannot be used.
+
+
+Command modifiers are not ignored ~
+								*E1176*
+Using a command modifier for a command that does not use it gives an error.
+								*E1082*
+Also, using a command modifier without a following command is now an error.
+
+
+Dictionary literals ~
+						*vim9-literal-dict* *E1014*
+Traditionally Vim has supported dictionary literals with a {} syntax: >
+	let dict = {'key': value}
+
+Later it became clear that using a simple text key is very common, thus
+literal dictionaries were introduced in a backwards compatible way: >
+	let dict = #{key: value}
+
+However, this #{} syntax is unlike any existing language.  As it turns out
+that using a literal key is much more common than using an expression, and
+considering that JavaScript uses this syntax, using the {} form for dictionary
+literals is considered a much more useful syntax.  In Vim9 script the {} form
+uses literal keys: >
+	var dict = {key: value}
+
+This works for alphanumeric characters, underscore and dash.  If you want to
+use another character, use a single or double quoted string: >
+	var dict = {'key with space': value}
+	var dict = {"key\twith\ttabs": value}
+	var dict = {'': value}			# empty key
+<							*E1139*
+In case the key needs to be an expression, square brackets can be used, just
+like in JavaScript: >
+	var dict = {["key" .. nr]: value}
+
+The key type can be string, number, bool or float.  Other types result in an
+error.  Without using [] the value is used as a string, keeping leading zeros.
+An expression given with [] is evaluated and then converted to a string.
+Leading zeros will then be dropped: >
+	var dict = {000123: 'without', [000456]: 'with'}
+	echo dict
+	{'456': 'with', '000123': 'without'}
+A float only works inside [] because the dot is not accepted otherwise: >
+	var dict = {[00.013]: 'float'}
+	echo dict
+	{'0.013': 'float'}
+
+
+No :xit, :t, :k, :append, :change or :insert ~
+							*E1100*
+These commands are too easily confused with local variable names.
+Instead of `:x` or `:xit` you can use `:exit`.
+Instead of `:t` you can use `:copy`.
+Instead of `:k` you can use `:mark`.
+
+
+Comparators ~
+
+The 'ignorecase' option is not used for comparators that use strings.
+Thus "=~" works like "=~#".
+
+"is" and "isnot" (|expr-is| and |expr-isnot|) when used on strings now return
+false.  In legacy script they just compare the strings, in |Vim9| script they
+check identity, and strings are copied when used, thus two strings are never
+the same (this might change someday if strings are not copied but reference
+counted).
+
+
+Abort after error ~
+
+In legacy script, when an error is encountered, Vim continues to execute
+following lines.  This can lead to a long sequence of errors and need to type
+CTRL-C to stop it.  In Vim9 script execution of commands stops at the first
+error.  Example: >
+	vim9script
+	var x = does-not-exist
+	echo 'not executed'
+
+
+For loop ~
+							*E1254*
+The loop variable must not be declared yet: >
+	var i = 1
+	for i in [1, 2, 3]   # Error!
+
+It is possible to use a global variable though: >
+	g:i = 1
+	for g:i in [1, 2, 3]
+	  echo g:i
+	endfor
+
+Legacy Vim script has some tricks to make a for loop over a list handle
+deleting items at the current or previous item.  In Vim9 script it just uses
+the index, if items are deleted then items in the list will be skipped.
+Example legacy script: >
+	let l = [1, 2, 3, 4]
+	for i in l
+	   echo i
+	   call remove(l, index(l, i))
+	endfor
+Would echo:
+	1
+	2
+	3
+	4
+In compiled Vim9 script you get:
+	1
+	3
+Generally, you should not change the list that is iterated over.  Make a copy
+first if needed.
+When looping over a list of lists, the nested lists can be changed.  The loop
+variable is "final", it cannot be changed but what its value can be changed.
+							*E1306*
+The depth of loops, :for and :while loops added together, cannot exceed 10.
+
+
+Conditions and expressions ~
+						*vim9-boolean*
+Conditions and expressions are mostly working like they do in other languages.
+Some values are different from legacy Vim script:
+	value		legacy Vim script	Vim9 script ~
+	0		falsy			falsy
+	1		truthy			truthy
+	99		truthy			Error!
+	"0"		falsy			Error!
+	"99"		truthy			Error!
+	"text"		falsy			Error!
+
+For the "??" operator and when using "!" then there is no error, every value
+is either falsy or truthy.  This is mostly like JavaScript, except that an
+empty list and dict is falsy:
+
+	type		truthy when ~
+	bool		true, v:true or 1
+	number		non-zero
+	float		non-zero
+	string		non-empty
+	blob		non-empty
+	list		non-empty (different from JavaScript)
+	dictionary	non-empty (different from JavaScript)
+	func		when there is a function name
+	special		true or v:true
+	job		when not NULL
+	channel		when not NULL
+	class		when not NULL
+	object		when not NULL (TODO: when isTrue() returns true)
+
+The boolean operators "||" and "&&" expect the values to be boolean, zero or
+one: >
+	1 || false   == true
+	0 || 1       == true
+	0 || false   == false
+	1 && true    == true
+	0 && 1       == false
+	8 || 0	     Error!
+	'yes' && 0   Error!
+	[] || 99     Error!
+
+When using "!" for inverting, there is no error for using any type and the
+result is a boolean.  "!!" can be used to turn any value into boolean: >
+	!'yes'			== false
+	!![]			== false
+	!![1, 2, 3]		== true
+
+When using "`.."` for string concatenation arguments of simple types are
+always converted to string: >
+	'hello ' .. 123  == 'hello 123'
+	'hello ' .. v:true  == 'hello true'
+
+Simple types are Number, Float, Special and Bool.  For other types |string()|
+should be used.
+			*false* *true* *null* *null_blob* *null_channel*
+			*null_dict* *null_function* *null_job* *null_list*
+			*null_partial* *null_string* *E1034*
+In Vim9 script one can use the following predefined values: >
+	true
+	false
+	null
+	null_blob
+	null_channel
+	null_dict
+	null_function
+	null_job
+	null_list
+	null_partial
+	null_string
+`true` is the same as `v:true`, `false` the same as `v:false`, `null` the same
+as `v:null`.
+
+While `null` has the type "special", the other "null_" values have the type
+indicated by their name.  Quite often a null value is handled the same as an
+empty value, but not always.  The values can be useful to clear a script-local
+variable, since they cannot be deleted with `:unlet`.  E.g.: >
+	var theJob = job_start(...)
+	# let the job do its work
+	theJob = null_job
+
+The values can also be useful as the default value for an argument: >
+	def MyFunc(b: blob = null_blob)
+	   if b == null_blob
+	      # b argument was not given
+
+It is possible to compare `null`  with any value, this will not give a type
+error.  However, comparing `null` with a number, float or bool will always
+result in `false`.  This is different from legacy script, where comparing
+`null` with zero or `false` would return `true`.
+							*vim9-false-true*
+When converting a boolean to a string `false` and `true` are used, not
+`v:false` and `v:true` like in legacy script.  `v:none` has no `none`
+replacement, it has no equivalent in other languages.
+							*vim9-string-index*
+Indexing a string with [idx] or taking a slice with [idx : idx] uses character
+indexes instead of byte indexes.  Composing characters are included.
+Example: >
+	echo 'bár'[1]
+In legacy script this results in the character 0xc3 (an illegal byte), in Vim9
+script this results in the string 'á'.
+A negative index is counting from the end, "[-1]" is the last character.
+To exclude the last character use |slice()|.
+To count composing characters separately use |strcharpart()|.
+If the index is out of range then an empty string results.
+
+In legacy script "++var" and "--var" would be silently accepted and have no
+effect.  This is an error in Vim9 script.
+
+Numbers starting with zero are not considered to be octal, only numbers
+starting with "0o" are octal: "0o744". |scriptversion-4|
+
+
+What to watch out for ~
+							*vim9-gotchas*
+Vim9 was designed to be closer to often used programming languages, but at the
+same time tries to support the legacy Vim commands.  Some compromises had to
+be made.  Here is a summary of what might be unexpected.
+
+Ex command ranges need to be prefixed with a colon. >
+	->		  legacy Vim: shifts the previous line to the right
+	->func()	  Vim9: method call in a continuation line
+	:->		  Vim9: shifts the previous line to the right
+
+	%s/a/b		  legacy Vim: substitute on all lines
+	x = alongname
+	     % another	  Vim9: modulo operator in a continuation line
+	:%s/a/b		  Vim9: substitute on all lines
+	't		  legacy Vim: jump to mark t
+	'text'->func()	  Vim9: method call
+	:'t		  Vim9: jump to mark t
+
+Some Ex commands can be confused with assignments in Vim9 script: >
+	g:name = value    # assignment
+	:g:pattern:cmd	  # :global command
+
+To avoid confusion between a `:global` or `:substitute` command and an
+expression or assignment, a few separators cannot be used when these commands
+are abbreviated to a single character: ':', '-' and '.'. >
+	g:pattern:cmd	  # invalid command - ERROR
+	s:pattern:repl	  # invalid command - ERROR
+	g-pattern-cmd	  # invalid command - ERROR
+	s-pattern-repl	  # invalid command - ERROR
+	g.pattern.cmd	  # invalid command - ERROR
+	s.pattern.repl	  # invalid command - ERROR
+
+Also, there cannot be a space between the command and the separator: >
+	g /pattern/cmd	  # invalid command - ERROR
+	s /pattern/repl	  # invalid command - ERROR
+
+Functions defined with `:def` compile the whole function.  Legacy functions
+can bail out, and the following lines are not parsed: >
+	func Maybe()
+	  if !has('feature')
+	    return
+	  endif
+	  use-feature
+	endfunc
+Vim9 functions are compiled as a whole: >
+	def Maybe()
+	  if !has('feature')
+	    return
+	  endif
+	  use-feature  # May give a compilation error
+	enddef
+For a workaround, split it in two functions: >
+	func Maybe()
+	  if has('feature')
+	    call MaybeInner()
+	  endif
+	endfunc
+	if has('feature')
+	  def MaybeInner()
+	    use-feature
+	  enddef
+	endif
+Or put the unsupported code inside an `if` with a constant expression that
+evaluates to false: >
+	def Maybe()
+	  if has('feature')
+	    use-feature
+	  endif
+	enddef
+The `exists_compiled()` function can also be used for this.
+							*vim9-user-command*
+Another side effect of compiling a function is that the presence of a user
+command is checked at compile time.  If the user command is defined later an
+error will result.  This works: >
+	command -nargs=1 MyCommand echom <q-args>
+	def Works()
+	  MyCommand 123
+	enddef
+This will give an error for "MyCommand" not being defined: >
+	def Works()
+	  command -nargs=1 MyCommand echom <q-args>
+	  MyCommand 123
+	enddef
+A workaround is to invoke the command indirectly with `:execute`: >
+	def Works()
+	  command -nargs=1 MyCommand echom <q-args>
+	  execute 'MyCommand 123'
+	enddef
+
+Note that for unrecognized commands there is no check for "|" and a following
+command.  This will give an error for missing `endif`: >
+	def Maybe()
+	  if has('feature') | use-feature | endif
+	enddef
+
+Other differences ~
+
+Patterns are used like 'magic' is set, unless explicitly overruled.
+The 'edcompatible' option value is not used.
+The 'gdefault' option value is not used.
+
+You may also find this wiki useful.  It was written by an early adopter of
+Vim9 script: https://github.com/lacygoill/wiki/blob/master/vim/vim9.md
+
+							*:++* *:--*
+The ++ and -- commands have been added.  They are very similar to adding or
+subtracting one: >
+		++var
+		var += 1
+		--var
+		var -= 1
+
+Using ++var or --var in an expression is not supported yet.
+
+==============================================================================
+
+3. New style functions					*fast-functions*
+
+							*:def* *E1028*
+:def[!] {name}([arguments])[: {return-type}]
+			Define a new function by the name {name}.  The body of
+			the function follows in the next lines, until the
+			matching `:enddef`. *E1073*
+							*E1011*
+			The {name} must be less than 100 bytes long.
+					*E1003* *E1027* *E1056* *E1059*
+			The type of value used with `:return` must match
+			{return-type}.  When {return-type} is omitted or is
+			"void" the function is not expected to return
+			anything.
+							*E1077* *E1123*
+			{arguments} is a sequence of zero or more argument
+			declarations.  There are three forms:
+				{name}: {type}
+				{name} = {value}
+				{name}: {type} = {value}
+			The first form is a mandatory argument, the caller
+			must always provide them.
+			The second and third form are optional arguments.
+			When the caller omits an argument the {value} is used.
+
+			The function will be compiled into instructions when
+			called, or when `:disassemble` or `:defcompile` is
+			used.  Syntax and type errors will be produced at that
+			time.
+
+			It is possible to nest `:def` inside another `:def` or
+			`:function` up to about 50 levels deep.
+							*E1117*
+			[!] 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* *E1057* *E1152* *E1173*
+:enddef			End of a function defined with `:def`. It should be on
+			a line by its own.
+
+You may also find this wiki useful.  It was written by an early adopter of
+Vim9 script: https://github.com/lacygoill/wiki/blob/master/vim/vim9.md
+
+If the script the function is defined in is Vim9 script, then script-local
+variables can be accessed without the "s:" prefix.  They must be defined
+before the function is compiled.  If the script the function is defined in is
+legacy script, then script-local variables must be accessed with the "s:"
+prefix if they do not exist at the time of compiling.
+							*E1269*
+Script-local variables in a |Vim9| script must be declared at the script
+level.  They cannot be created in a function, also not in a legacy function.
+
+						*:defc* *:defcompile*
+:defc[ompile]		Compile functions defined in the current script that
+			were not compiled yet.
+			This will report any errors found during compilation.
+			This excludes functions defined inside a class.
+
+:defc[ompile] {func}
+:defc[ompile] debug {func}
+:defc[ompile] profile {func}
+			Compile function {func}, if needed.  Use "debug" and
+			"profile" to specify the compilation mode.
+			This will report any errors found during compilation.
+			{func} call also be "ClassName.functionName" to
+			compile a function or method in a class.
+			{func} call also be "ClassName" to compile all
+			functions and methods in a class.
+
+						*:disa* *:disassemble*
+:disa[ssemble] {func}	Show the instructions generated for {func}.
+			This is for debugging and testing. *E1061*
+			Note that for command line completion of {func} you
+			can prepend "s:" to find script-local functions.
+
+:disa[ssemble] profile {func}
+			Like `:disassemble` but with the instructions used for
+			profiling.
+
+:disa[ssemble] debug {func}
+			Like `:disassemble` but with the instructions used for
+			debugging.
+
+Limitations ~
+
+Local variables will not be visible to string evaluation.  For example: >
+	def MapList(): 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 MapList(): list<string>
+	  var list = ['aa', 'bb', 'cc', 'dd']
+	  return range(1, 2)->map((_, v) => list[v])
+	enddef
+
+For commands that are not compiled, such as `:edit`, backtick expansion can be
+used and it can use the local scope.  Example: >
+	def Replace()
+	  var fname = 'blah.txt'
+	  edit `=fname`
+	enddef
+
+Closures defined in a loop will share the same context.  For example: >
+	var flist: list<func>
+	for i in range(5)
+	  var inloop = i
+	  flist[i] = () => inloop
+	endfor
+	echo range(5)->map((i, _) => flist[i]())
+	# Result: [4, 4, 4, 4, 4]
+<							*E1271*
+A closure must be compiled in the context that it is defined in, so that
+variables in that context can be found.  This mostly happens correctly, except
+when a function is marked for debugging with `:breakadd` after it was compiled.
+Make sure to define the breakpoint before compiling the outer function.
+
+The "inloop" variable will exist only once, all closures put in the list refer
+to the same instance, which in the end will have the value 4.  This is
+efficient, also when looping many times.  If you do want a separate context
+for each closure, call a function to define it: >
+	def GetClosure(i: number): func
+	  var infunc = i
+	  return () => infunc
+	enddef
+
+	var flist: list<func>
+	for i in range(5)
+	  flist[i] = GetClosure(i)
+	endfor
+	echo range(5)->map((i, _) => flist[i]())
+	# Result: [0, 1, 2, 3, 4]
+
+In some situations, especially when calling a Vim9 closure from legacy
+context, the evaluation will fail.  *E1248*
+
+Note that at the script level the loop variable will be invalid after the
+loop, also when used in a closure that is called later, e.g. with a timer.
+This will generate error |E1302|: >
+	for n in range(4)
+	    timer_start(500 * n, (_) => {
+	          echowin n
+	       })
+	endfor
+
+You need to use a block and define a variable there, and use that one in the
+closure: >
+	for n in range(4)
+	{
+	   var nr = n
+	   timer_start(500 * n, (_) => {
+	          echowin nr
+	      })
+	}
+	endfor
+
+Using `:echowindow` is useful in a timer, the messages go into a popup and will
+not interfere with what the user is doing when it triggers.
+
+
+Converting a function from legacy to Vim9 ~
+					*convert_legacy_function_to_vim9*
+These are the most changes that need to be made to convert a legacy function
+to a Vim9 function:
+
+- Change `func` or `function` to `def`.
+- Change `endfunc` or `endfunction` to `enddef`.
+- Add types to the function arguments.
+- If the function returns something, add the return type.
+- Change comments to start with # instead of ".
+
+  For example, a legacy function: >
+	func MyFunc(text)
+	  " function body
+	endfunc
+<  Becomes: >
+	def MyFunc(text: string): number
+	  # function body
+	enddef
+
+- Remove "a:" used for arguments. E.g.: >
+	return len(a:text)
+<  Becomes: >
+	return len(text)
+
+- Change `let` used to declare a variable to `var`.
+- Remove `let` used to assign a value to a variable.  This is for local
+  variables already declared and b: w: g: and t: variables.
+
+  For example, legacy function: >
+	  let lnum = 1
+	  let lnum += 3
+	  let b:result = 42
+<  Becomes: >
+	  var lnum = 1
+	  lnum += 3
+	  b:result = 42
+
+- Insert white space in expressions where needed.
+- Change "." used for concatenation to "..".
+
+  For example, legacy function: >
+	  echo line(1).line(2)
+<  Becomes: >
+	  echo line(1) .. line(2)
+
+- line continuation does not always require a backslash: >
+	echo ['one',
+		\ 'two',
+		\ 'three'
+		\ ]
+<  Becomes: >
+	echo ['one',
+		'two',
+		'three'
+		]
+
+
+Calling a function in an expr option ~
+							*expr-option-function*
+The value of a few options, such as 'foldexpr', is an expression that is
+evaluated to get a value.  The evaluation can have quite a bit of overhead.
+One way to minimize the overhead, and also to keep the option value very
+simple, is to define a compiled function and set the option to call it
+without arguments.  Example: >
+	vim9script
+	def MyFoldFunc(): any
+	   ... compute fold level for line v:lnum
+	   return level
+	enddef
+	set foldexpr=s:MyFoldFunc()
+
+==============================================================================
+
+4. Types					*vim9-types*
+					*E1008* *E1009* *E1010* *E1012*
+					*E1013* *E1029* *E1030*
+The following builtin types are supported:
+	bool
+	number
+	float
+	string
+	blob
+	list<{type}>
+	dict<{type}>
+	job
+	channel
+	func
+	func: {type}
+	func({type}, ...)
+	func({type}, ...): {type}
+	void
+
+Not supported yet:
+	tuple<a: {type}, b: {type}, ...>
+
+These types can be used in declarations, but no simple value will actually
+have the "void" type.  Trying to use a void (e.g. a function without a
+return value) results in error *E1031*  *E1186* .
+
+There is no array type, use list<{type}> instead.  For a list constant an
+efficient implementation is used that avoids allocating a lot of small pieces
+of memory.
+							*E1005* *E1007*
+A partial and function can be declared in more or less specific ways:
+func				any kind of function reference, no type
+				checking for arguments or return value
+func: void			any number and type of arguments, no return
+				value
+func: {type}			any number and type of arguments with specific
+				return type
+
+func()				function with no argument, does not return a
+				value
+func(): void			same
+func(): {type}			function with no argument and return type
+
+func({type})			function with argument type, does not return
+				a value
+func({type}): {type}		function with argument type and return type
+func(?{type})			function with type of optional argument, does
+				not return a value
+func(...{type})			function with type of variable number of
+				arguments, does not return a value
+func({type}, ?{type}, ...{type}): {type}
+				function with:
+				- type of mandatory argument
+				- type of optional argument
+				- type of variable number of arguments
+				- return type
+
+If the return type is "void" the function does not return a value.
+
+The reference can also be a |Partial|, in which case it stores extra arguments
+and/or a dictionary, which are not visible to the caller.  Since they are
+called in the same way the declaration is the same.
+
+Custom types can be defined with `:type`: >
+	:type MyList list<string>
+Custom types must start with a capital letter, to avoid name clashes with
+builtin types added later, similarly to user functions.
+{not implemented yet}
+
+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.
+
+Global, buffer, window and tab page variables do not have a specific type, the
+value can be changed at any time, possibly changing the type.  Therefore, in
+compiled code the "any" type is assumed.
+
+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]
+At compile time Vim doesn't know the type of "g:two" and the expression type
+becomes list<any>.  An instruction is generated to check the list type before
+doing the assignment, which is a bit inefficient.
+						*type-casting* *E1104*
+To avoid this, use a type cast: >
+	var l: list<number> = [1, <number>g:two]
+The compiled code will then only check that "g:two" is a number and give an
+error if it isn't.  This is called type casting.
+
+The syntax of a type cast is:  "<" {type} ">".  There cannot be white space
+after the "<" or before the ">" (to avoid them being confused with
+smaller-than and bigger-than operators).
+
+The semantics is that, if needed, a runtime type check is performed.  The
+value is not actually changed.  If you need to change the type, e.g. to change
+it to a string, use the |string()| function.  Or use |str2nr()| to convert a
+string to a number.
+
+If a type is given where it is not expected you can get *E1272* .
+
+If a type is incomplete you get *E1363*, e.g. when you have an object for
+which the class is not known (usually that is a null object).
+
+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
+dictionary.  If there is a mix of types, the "any" type is used. >
+	[1, 2, 3]	list<number>
+	['a', 'b', 'c']	list<string>
+	[1, 'x', 3]	list<any>
+
+The common type of function references, if they do not all have the same
+number of arguments, uses "(...)" to indicate the number of arguments is not
+specified.  For example: >
+	def Foo(x: bool)
+	enddef
+	def Bar(x: bool, y: bool)
+	enddef
+	var funclist = [Foo, Bar]
+	echo funclist->typename()
+Results in:
+	list<func(...)>
+
+For script-local variables in Vim9 script the type is checked, also when the
+variable was declared in a legacy function.
+
+When a type has been declared this is attached to a List or Dictionary.  When
+later some expression attempts to change the type an error will be given: >
+	var ll: list<number> = [1, 2, 3]
+	ll->extend(['x'])  # Error, 'x' is not a number
+
+If the type is not declared then it is allowed to change: >
+	[1, 2, 3]->extend(['x'])  # result: [1, 2, 3, 'x']
+
+For a variable declaration an inferred type matters: >
+	var ll = [1, 2, 3]
+	ll->extend(['x'])  # Error, 'x' is not a number
+That is because the declaration looks like a list of numbers, thus is
+equivalent to: >
+	var ll: list<number> = [1, 2, 3]
+If you do want a more permissive list you need to declare the type: >
+	var ll: list<any> = [1, 2, 3]
+	ll->extend(['x'])  # OK
+
+
+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 (and no error message) if the
+string doesn't start with a number.  Quite often this leads to hard-to-find
+bugs. e.g.: >
+	echo 123 == '123'
+<	1 ~
+With an accidental space: >
+	echo 123 == ' 123'
+<	0 ~
+							*E1206* *E1210* *E1212*
+In Vim9 script this has been made stricter.  In most places it works just as
+before if the value used matches the expected type.  There will sometimes be
+an error, thus breaking backwards compatibility.  For example:
+- Using a number other than 0 or 1 where a boolean is expected.  *E1023*
+- Using a string value when setting a number option.
+- Using a number where a string is expected.   *E1024* *E1105*
+
+One consequence is that the item type of a list or dict given to |map()| must
+not change, if the type was declared.  This will give an error in Vim9
+script: >
+	var mylist: list<number> = [1, 2, 3]
+	echo map(mylist, (i, v) => 'item ' .. i)
+<	E1012: Type mismatch; expected number but got string in map() ~
+
+Instead use |mapnew()|, it creates a new list: >
+	var mylist: list<number> = [1, 2, 3]
+	echo mapnew(mylist, (i, v) => 'item ' .. i)
+<	['item 0', 'item 1', 'item 2'] ~
+
+If the item type was not declared or determined to be "any" it can change to a
+more specific type.  E.g. when a list of mixed types gets changed to a list of
+strings: >
+	var mylist = [1, 2.0, '3']
+	# typename(mylist) == "list<any>"
+	map(mylist, (i, v) => 'item ' .. i)
+	# typename(mylist) == "list<string>", no error
+
+There is a subtle difference between using a list constant directly and
+through a variable declaration.  Because of type inference, when using a list
+constant to initialize a variable, this also sets the declared type: >
+	var mylist = [1, 2, 3]
+	# typename(mylist) == "list<number>"
+	echo map(mylist, (i, v) => 'item ' .. i)  # Error!
+
+When using the list constant directly, the type is not declared and is allowed
+to change: >
+	echo map([1, 2, 3], (i, v) => 'item ' .. i)  # OK
+
+The reasoning behind this is that when a type is declared and the list is
+passed around and changed, the declaration must always hold.  So that you can
+rely on the type to match the declared type.  For a constant this is not
+needed.
+
+								*E1158*
+Same for |extend()|, use |extendnew()| instead, and for |flatten()|, use
+|flattennew()| instead.  Since |flatten()| is intended to always change the
+type, it can not be used in Vim9 script.
+
+			 *E1211* *E1217* *E1218* *E1219* *E1220* *E1221*
+			 *E1222* *E1223* *E1224* *E1225* *E1226* *E1227*
+			 *E1228* *E1238* *E1250* *E1251* *E1252* *E1256*
+			 *E1297* *E1298* *E1301*
+Types are checked for most builtin functions to make it easier to spot
+mistakes.
+
+==============================================================================
+
+5. Namespace, Import and Export
+					*vim9script* *vim9-export* *vim9-import*
+
+A Vim9 script can be written to be imported.  This means that some items are
+intentionally exported, made available to other scripts.  When the exporting
+script is imported in another script, these exported items can then be used in
+that script.  All the other items remain script-local in the exporting script
+and cannot be accessed by the importing script.
+
+This mechanism exists for writing a script that can be sourced (imported) by
+other scripts, while making sure these other scripts only have access to what
+you want them to.  This also avoids using the global namespace, which has a
+risk of name collisions.  For example when you have two plugins with similar
+functionality.
+
+You can cheat by using the global namespace explicitly.  That should be done
+only for things that really are global.
+
+
+Namespace ~
+							*vim9-namespace*
+To recognize a file that can be imported the `vim9script` statement must
+appear as the first statement in the file (see |vim9-mix| for an exception).
+It tells Vim to interpret the 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.
+							*E1101*
+The variables at the file level are very much like the script-local "s:"
+variables in legacy Vim script, but the "s:" is omitted.  And they cannot be
+deleted.
+
+In Vim9 script the global "g:" namespace can still be used as before.  And the
+"w:", "b:" and "t:" namespaces.  These have in common that variables are not
+declared, have no specific type and they can be deleted.  *E1304*
+
+A side effect of `:vim9script` is that the 'cpoptions' option is set to the
+Vim default value, like with: >
+	:set cpo&vim
+One of the effects is that |line-continuation| is always enabled.
+The original value of 'cpoptions' is restored at the end of the script, while
+flags added or removed in the script are also added to or removed from the
+original value to get the same effect.  The order of flags may change.
+In the |vimrc| file sourced on startup this does not happen.
+
+							*vim9-mix*
+There is one way to use both legacy and Vim9 syntax in one script file: >
+	" comments may go here
+	if !has('vim9script')
+	   " legacy script commands go here
+	   finish
+	endif
+	vim9script
+	# Vim9 script commands go here
+This allows for writing a script that takes advantage of the Vim9 script
+syntax if possible, but will also work on a Vim version without it.
+
+This can only work in two ways:
+1. The "if" statement evaluates to false, the commands up to `endif` are
+   skipped and `vim9script` is then the first command actually executed.
+2. The "if" statement evaluates to true, the commands up to `endif` are
+   executed and `finish` bails out before reaching `vim9script`.
+
+
+Export ~
+							*: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 ...
+	export interface MyClass ...
+<							*E1043* *E1044*
+As this suggests, only constants, variables, `:def` functions and classes can
+be exported. {not implemented yet: class, interface}
+
+							*E1042*
+`:export` can only be used in Vim9 script, at the script level.
+
+
+Import ~
+				*:import* *:imp* *E1094* *E1047* *E1262*
+				*E1048* *E1049* *E1053* *E1071* *E1088* *E1236*
+The exported items can be imported in another script. The import syntax has
+two forms. The simple form: >
+	import {filename}
+<
+Where {filename} is an expression that must evaluate to a string.  In this
+form the filename should end in ".vim" and the portion before ".vim" will
+become the script local name of the namespace. For example: >
+	import "myscript.vim"
+<
+This makes each exported item in "myscript.vim" available as "myscript.item".
+						*:import-as* *E1257* *E1261*
+In case the name is long or ambiguous, this form can be used to specify
+another name: >
+	import {longfilename} as {name}
+<
+In this form {name} becomes a specific script local name for the imported
+namespace.  Therefore {name} must consist of letters, digits and '_', like
+|internal-variables|.  The {longfilename} expression must evaluate to any
+filename.  For example: >
+	import "thatscript.vim.v2" as that
+<						*E1060* *E1258* *E1259* *E1260*
+Then you can use "that.item", etc.  You are free to choose the name "that".
+Use something that will be recognized as referring to the imported script.
+Avoid command names, command modifiers and builtin function names, because the
+name will shadow them.  Better not start the name starts with a capital
+letter, since it can then also shadow global user commands and functions.
+Also, you cannot use the name for something else in the script, such as a
+function or variable name.
+
+In case the dot in the name is undesired, a local reference can be made for a
+function: >
+	var LongFunc = that.LongFuncName
+
+This also works for constants: >
+	const MAXLEN = that.MAX_LEN_OF_NAME
+
+This does not work for variables, since the value would be copied once and
+when changing the variable the copy will change, not the original variable.
+You will need to use the full name, with the dot.
+
+`:import` can not be used in a function.  Imported items are intended to exist
+at the script level and only imported once.
+
+The script name after `import` can be:
+- A relative path, starting "." or "..".  This finds a file relative to the
+  location of the script file itself.  This is useful to split up a large
+  plugin into several files.
+- An absolute path, starting with "/" on Unix or "D:/" on MS-Windows.  This
+  will rarely be used.
+- A path not being relative or absolute.  This will be found in the
+  "import" subdirectories of 'runtimepath' entries.  The name will usually be
+  longer and unique, to avoid loading the wrong file.
+  Note that "after/import" is not used.
+
+If the name does not end in ".vim" then the use of "as name" is required.
+
+Once a vim9 script file has been imported, the result is cached and used the
+next time the same script is imported.  It will not be read again.
+
+It is not allowed to import the same script twice, also when using two
+different "as" names.
+
+When using the imported name the dot and the item name must be in the same
+line, there can be no line break: >
+	echo that.
+		name   # Error!
+	echo that
+		.name  # Error!
+<						*import-map*
+When you've imported a function from one script into a vim9 script you can
+refer to the imported function in a mapping by prefixing it with |<SID>|: >
+	noremap <silent> ,a :call <SID>name.Function()<CR>
+
+When the mapping is defined "<SID>name." will be replaced with <SNR> and the
+script ID of the imported script.
+An even simpler solution is using |<ScriptCmd>|: >
+	noremap ,a <ScriptCmd>name.Function()<CR>
+
+Note that this does not work for variables, only for functions.
+
+					    *import-legacy* *legacy-import*
+`:import` can also be used in legacy Vim script.  The imported namespace still
+becomes script-local, even when the "s:" prefix is not given. For example: >
+        import "myfile.vim"
+	call s:myfile.MyFunc()
+
+And using the "as name" form: >
+	import "otherfile.vim9script" as that
+	call s:that.OtherFunc()
+
+However, the namespace cannot be resolved on its own: >
+	import "that.vim"
+	echo s:that
+	" ERROR: E1060: Expected dot after name: s:that
+<
+This also affects the use of |<SID>| in the legacy mapping context.  Since
+|<SID>| is only a valid prefix for a function and NOT for a namespace, you
+cannot use it
+to scope a function in a script local namespace. Instead of prefixing the
+function with |<SID>| you should use|<ScriptCmd>|. For example: >
+	noremap ,a <ScriptCmd>:call s:that.OtherFunc()<CR>
+<
+							*:import-cycle*
+The `import` commands are executed when encountered.  If script A imports
+script B, and B (directly or indirectly) imports A, this will be skipped over.
+At this point items in A after "import B" will not have been processed and
+defined yet.  Therefore cyclic imports can exist and not result in an error
+directly, but may result in an error for items in A after "import B" not being
+defined.  This does not apply to autoload imports, see the next section.
+
+
+Importing an autoload script ~
+					*vim9-autoload* *import-autoload*
+For optimal startup speed, loading scripts should be postponed until they are
+actually needed.  Using the autoload mechanism is recommended:
+							*E1264*
+1. In the plugin define user commands, functions and/or mappings that refer to
+   items imported from an autoload script. >
+	import autoload 'for/search.vim'
+	command -nargs=1 SearchForStuff search.Stuff(<f-args>)
+
+<   This goes in .../plugin/anyname.vim.  "anyname.vim" can be freely chosen.
+   The "SearchForStuff" command is now available to the user.
+
+   The "autoload" argument to `:import` means that the script is not loaded
+   until one of the items is actually used.  The script will be found under
+   the "autoload" directory in 'runtimepath' instead of the "import"
+   directory.  Alternatively a relative or absolute name can be used, see
+   below.
+
+2. In the autoload script put the bulk of the code. >
+	vim9script
+	export def Stuff(arg: string)
+	  ...
+
+<   This goes in .../autoload/for/search.vim.
+
+   Putting the "search.vim" script under the "/autoload/for/" directory has
+   the effect that "for#search#" will be prefixed to every exported item.  The
+   prefix is obtained from the file name, as you would to manually in a
+   legacy autoload script.  Thus the exported function can be found with
+   "for#search#Stuff", but you would normally use `import autoload` and not
+   use the prefix (which has the side effect of loading the autoload script
+   when compiling a function that encounters this name).
+
+   You can split up the functionality and import other scripts from the
+   autoload script as you like.  This way you can share code between plugins.
+
+Searching for the autoload script in all entries in 'runtimepath' can be a bit
+slow.  If the plugin knows where the script is located, quite often a relative
+path can be used.  This avoids the search and should be quite a bit faster.
+Another advantage is that the script name does not need to be unique.  An
+absolute path is also possible.  Examples: >
+	import autoload '../lib/implement.vim'
+	import autoload MyScriptsDir .. '/lib/implement.vim'
+
+For defining a mapping that uses the imported autoload script the special key
+|<ScriptCmd>| is useful.  It allows for a command in a mapping to use the
+script context of where the mapping was defined.
+
+When compiling a `:def` function and a function in an autoload script is
+encountered, the script is not loaded until the `:def` function is called.
+This also means you get any errors only at runtime, since the argument and
+return types are not known yet.  If you would use the name with '#' characters
+then the autoload script IS loaded.
+
+Be careful to not refer to an item in an autoload script that does trigger
+loading it unintentionally.  For example, when setting an option that takes a
+function name, make sure to use a string, not a function reference: >
+	import autoload 'qftf.vim'
+	&quickfixtextfunc = 'qftf.Func'  # autoload script NOT loaded
+	&quickfixtextfunc = qftf.Func    # autoload script IS loaded
+On the other hand, it can be useful to load the script early, at a time when
+any errors should be given.
+
+For testing the |test_override()| function can be used to have the
+`import autoload` load the script right away, so that the items and types can
+be checked without waiting for them to be actually used: >
+	test_override('autoload', 1)
+Reset it later with: >
+	test_override('autoload', 0)
+Or: >
+	test_override('ALL', 0)
+
+
+==============================================================================
+
+6. Classes and interfaces				*vim9-classes*
+
+In legacy script a Dictionary could be used as a kind-of object, by adding
+members that are functions.  However, this is quite inefficient and requires
+the writer to do the work of making sure all the objects have the right
+members.  See |Dictionary-function|.
+
+In |Vim9| script you can have classes, objects and interfaces like in most
+popular object-oriented programming languages.  Since this is a lot of
+functionality it is located in a separate help file: |vim9class.txt|.
+
+
+==============================================================================
+
+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
+need to be handled, such as error messages and exceptions.  The need to create
+a dictionary for a: and l: scopes, the a:000 list and several others add too
+much overhead that cannot be avoided.
+
+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.
+
+
+Type checking ~
+
+When compiling lines of Vim commands into instructions as much as possible
+should be done at compile time.  Postponing it to runtime makes the execution
+slower and means mistakes are found only later.  For example, when
+encountering the "+" character and compiling this into a generic add
+instruction, at runtime the instruction would have to inspect the type 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 evaluating an
+  expression.
+- 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 also used by 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
+  goes against legacy Vim script and often leads to mistakes.  For that reason
+  we will keep using ".." for string concatenation.  Lua also uses ".." this
+  way.  And it allows for conversion to string for more values.
+- 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.  The |falsy-operator| was added for the mechanism to use a
+  default value.
+- 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.
+- TypeScript has various "Readonly" types, which have limited usefulness,
+  since a type cast can remove the immutable nature.  Vim locks the value,
+  which is more flexible, but is only checked at runtime.
+- TypeScript has a complicated "import" statement that does not match how the
+  Vim import mechanism works.  A much simpler mechanism is used instead, which
+  matches that the imported script is only sourced once.
+
+
+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 varies.  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 have 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 other languages are doing.
+Some details are unexpected and can be improved.  For example a boolean
+condition would accept a string, convert it to a number and check if the
+number is non-zero.  This is unexpected and often leads to mistakes, since
+text not starting with a number would be converted to zero, which is
+considered false.  Thus using a string for a condition would often not give an
+error and be considered false.  That is confusing.
+
+In Vim9 type checking is stricter to avoid mistakes.  Where a condition is
+used, e.g. with the `:if` command and the `||` operator, only boolean-like
+values are accepted:
+	true:  `true`, `v:true`, `1`, `0 < 9`
+	false: `false`, `v:false`, `0`, `0 > 9`
+Note that the number zero is false and the number one is true.  This is more
+permissive than most other languages.  It was done because many builtin
+functions return these values, and changing that causes more problems than it
+solves.  After using this for a while it turned out to work well.
+
+If you have any type of value and want to use it as a boolean, use the `!!`
+operator:
+	true: `!!'text'`   `!![99]`   `!!{'x': 1}`   `!!99`
+	false: `!!''`   `!![]`   `!!{}`
+
+From a language like JavaScript we have this handy construct: >
+	GetName() || 'unknown'
+However, this conflicts with only allowing a boolean for a condition.
+Therefore the "??" operator was added: >
+	GetName() ?? 'unknown'
+Here you can explicitly express your intention to use the value as-is and not
+result in a boolean. This is called the |falsy-operator|.
+
+
+Import and Export ~
+
+A problem of legacy Vim script is that by default all functions and variables
+are global.  It is possible to make them script-local, but then they are not
+available in other scripts.  This defies the concept of a package that only
+exports selected items and keeps the rest local.
+
+In Vim9 script a mechanism very similar to the JavaScript import and export
+mechanism is supported.  It is a variant to the existing `:source` command
+that works like one would expect:
+- Instead of making everything global by default, everything is script-local,
+  some of these are exported.
+- When importing a script the symbols that are imported are explicitly listed,
+  avoiding name conflicts and failures if functionality is added later.
+- The mechanism allows for writing a big, long script with a very clear API:
+  the exported functions, variables and classes.
+- By using relative paths loading can be much faster for an import inside of a
+  package, no need to search many directories.
+- Once an import has been used, its items are cached and loading it again is
+  not needed.
+- The Vim-specific use of "s:" to make things script-local can be dropped.
+
+When sourcing a Vim9 script (from a Vim9 or legacy script), only the items
+defined globally can be used, not the exported items.  Alternatives
+considered:
+- All the exported items become available as script-local items.  This makes
+  it uncontrollable what items get defined and likely soon leads to trouble.
+- Use the exported items and make them global.  Disadvantage is that it's then
+  not possible to avoid name clashes in the global namespace.
+- Completely disallow sourcing a Vim9 script, require using `:import`.  That
+  makes it difficult to use scripts for testing, or sourcing them from the
+  command line to try them out.
+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 well.
+
+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, a `:defcompile` command at the end of the script will help out.
+
+
+Why not use an existing 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 process, 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.
+
+
+
+ vim:tw=78:ts=8:noet:ft=help:norl: